SlideShare a Scribd company logo
1 of 49
Download to read offline
UNITTESTING NODE.JS
MIDDLEWARE
By Morris Singer
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
express and
ES15
Edition!
ABOUT ME
• Senior Software Engineer atVerilume
• I Like:
• Test-Driven Development
• Angular 1 and 2,Aurelia, Ionic, and
React.js, Node.js, and Cordova
AGENDA
• Define middleware and why it isn’t just
a fancy term for controllers or
endpoints.
• Review behavior-driven development
principles for unit testing.
• Argue why middleware are behavioral
units.
• Summarize common challenges testing
behavior in Express and Koa.
• Learn and implement a pattern for
Express and Koa Middleware.
• Answer questions. (10 minutes)
MIDDLEWARE
BuildingYour Product, One Layer at aTime
A SIMPLE CASE
One Middleware Per Endpoint
express
app.use(function (req, res, next) {
res.send('hello world');
});
A SIMPLE CASE
“Why is it called ‘Middleware’ anyway?”
app.use(function* (next) {
this.body = 'hello world';
});
• One Middleware Per Endpoint
MORE COMPLEX CASES
Two Ways of Stacking Middleware
Variadic Iterative
express
const middleware = [
function (req, res, next) {
req.message = 'HELLO WORLD';
next();
},
function (req, res, next) {
res.send(req.message.toLowerCase());
}
];
middleware.forEach(app.use);app.use(...middleware);
MORE COMPLEX CASES
Two Ways of Stacking Middleware
Variadic Iterative
app.use(...middleware);
const middleware = [
function* (next) => {
this.message = 'HELLO WORLD';
return yield next;
},
function* (next) => {
this.body = this.message.toLowerCase();
}
];
middleware.forEach(app.use);
THE MIDDLEWARE STACK
GET
Done
Generate
Message
Send Lowercase
Message
express
app.use(
function (req, res, next) {
req.message = 'HELLO WORLD';
next();
},
function (req, res, next) {
res.send(req.message.toLowerCase());
}
);
THE MIDDLEWARE STACK
GET
Done
Generate
Message
Assign Lowercase
to Body
app.use(
function (next) {
this.message = 'HELLO WORLD';
return yield next;
},
function (next) {
this.body = this.message.toLowerCase();
}
);
A B C
1
D E F
2
G H I
3
GET /
TEST BEHAVIOR
COMMON CHALLENGES
Or,Why Node Developers Often AvoidTDD
HTTP RESPONSETESTS
What happens when we add a middleware to the stack?
express
it('should return a 500 error', (done) => {
request({
method: 'POST',
url: 'http://localhost:3000/api/endpoint'
}, (error, response, body) => {
Assert.equal(response.statusCode, 500);
done();
});
});
TESTING MID-STACK
How do we pull out these anonymous functions?
express
const middleware = [
function (req, res, next) {
req.message = 'HELLO WORLD';
next();
},
function (req, res, next) {
res.send(req.message.toLowerCase());
}
];
middleware.forEach(app.use);
ILLUMINATINGTEST FAILURES
What happens if next() is not called?
express
import {httpMocks} from 'node-mocks-http';
it('should call next()', (done) => {
var req = httpMocks.createRequest(),
res = httpMocks.createResponse();
middleware(req, res, () => {
done();
});
});
KNOWING WHENTOTEST
When is the assertion run?
express
import {httpMocks} from 'node-mocks-http';
it('should call next()', () => {
var req = httpMocks.createRequest(),
res = httpMocks.createResponse();
middleware(req, res);
return Assert.equal(req.foo, 'bar');
});
TESTING WITH DATA
Where do data come from?
express
app.get('path/to/post', function (req, res, next) {
Post.findOne(params).exec(function (err, post) {
res.json(post);
});
});
DEALING WITH POLLUTION
How does one reset the data?
express
it('should update the first post', () => {
/* ... */
});
it('should get the first post', () => {
/* ... */
});
MOCKING DEPENDENCIES
How does one cut out the external data source?
express
app.get('endpoint', function (req, res, next) {
request({
method: 'GET',
url: 'http://example.com/api/call'
}, (error, response, body) => {
req.externalData = body;
next();
});
});
MIDDLEWARE + SEPARATION OF CONCERNS
+ FLOW CONTROL
The “Eureka” Moment
OVERVIEW
• Pull behavior into middleware and tests.
• Use promises or generators as flow control.
• Return client-server interaction to endpoint.
• Use promises or generators with Mocha.
PULL BEHAVIOR INTO
MIDDLEWARE,TESTS
Endpoint
Test
BehaviorBehavior
BehaviorBehavior
Endpoint
TestTest
Old Paradigm
New Paradigm
PULL BEHAVIOR INTO ENDPOINTS
Old Paradigm New Paradigm
N.B.:This only looks like a lot more code…
express
const middleware = [
function (req, res, next) {
/* Behavior */
},
function (req, res, next) {
/* Behavior */
}
];
app.use(...middleware);
const behavior = {
first: function () {},
second: function () {}
};
const middleware = [
function (req, res, next) {
behavior.first();
next();
},
function (req, res, next) {
behavior.second();
next();
}
];
app.use(...middleware);
PULL BEHAVIOR INTO ENDPOINTS
Old Paradigm New Paradigm
const middleware = [
function* (next) {
/* Behavior */
},
function* (next) {
/* Behavior */
}
];
app.use(...middleware);
const behavior = {
first: function* () {},
second: function* () {}
};
const middleware = [
function* (next) {
yield behavior.first();
return yield next;
},
function* (next) {
yield behavior.second();
return next;
}
];
app.use(...middleware);
USE PROMISES AS FLOW CONTROL
• Clean, standardized interface between asynchronous
behavior and endpoints.
• Both endpoints and tests can leverage the same mechanism
in the behavior for serializing logic.
express
USE PROMISES AS FLOW CONTROL
Old Paradigm
New Paradigm
express
export function middleware (req, res, next) {
/* Define behavior and call res.json(),
next(), etc. */
};
export function behavior () {
return new Promise((resolve, reject) => {
/* Define behavior and resolve or
reject promise. */
};
}
USE GENERATORS (WITH CO) AS FLOW CONTROL
• Same interface between asynchronous behavior and
middleware as already used between successive middleware.
• Both endpoints and tests can leverage the same mechanism
in the behavior for serializing logic.
CO
Generator based control flow goodness for nodejs and the browser,
using promises, letting you write non-blocking code in a nice-ish way.
https://www.npmjs.com/package/co
USE GENERATORS AS LINK BETWEEN
MIDDLEWARE AND ENDPOINTS
Old Paradigm
New Paradigm
export function* middleware (next) {
/* Call with assigned context and
leverage behavior on the Koa context,
yield next, etc.*/
};
export function* behavior () {
/* Define behavior and yield values. */
}
RETURN CLIENT-SERVER
INTERACTIONTO ENDPOINT
Endpoint
Res
Req
Behavior
Res
Req
Client
Endpoint
Value
Object
Behavior
Value
Object
Client
Old Paradigm
New Paradigm
RETURN CLIENT-SERVER
INTERACTIONTO ENDPOINT
Old Paradigm New Paradigm
express
const middleware = [
function (req, res, next) {},
function (req, res, next) {}
];
app.use(...middleware);
const behavior = [
function () {},
function () {}
];
const middleware = [
function (req, res, next) {
behavior[0](/* Pass objects, values */)
.then(function () { next(); })
.catch(res.json);
},
function (req, res, next) {
behavior[1](/* Pass objects, values */)
.then(function () { next(); })
.catch(res.json);
}
];
app.use(...middleware);
RETURN CLIENT-SERVER
INTERACTIONTO ENDPOINT
Old Paradigm New Paradigm
express
const middleware = [
function (req, res, next) {},
function (req, res, next) {}
];
app.use(...middleware);
const behavior = [
function () {},
function () {}
];
const middleware = behavior.map((func) => {
return function (req, res, next) {
func()
.then(function () { next(); })
.catch(res.json);
}
};
app.use(...middleware);
RETURN CLIENT-SERVER
INTERACTIONTO ENDPOINT
Old Paradigm New Paradigm
express
const middleware = [
function (req, res, next) {},
function (req, res, next) {}
];
app.use(...middleware);
const behavior = [
function () {},
function () {}
];
const middleware = behavior.map((func) => {
return function(args) {
return function (req, res, next) {
func()
.then(function () { next(); })
.catch(res.json);
}
}
};
app.use(
middleware[0](/* Pass objects, values */),
middleware[1](/* Pass objects, values */)
);
RETURN CLIENT-SERVER
INTERACTIONTO ENDPOINT
Old Paradigm New Paradigm
const middleware = [
function* (next) {},
function* (next) {}
];
app.use(...middleware);
const behavior = [
function* () {},
function* () {}
];
const middleware = [
function* (next) {
yield behavior[0](/* Pass objects, values */);
return yield next;
},
function* (next) {
yield behavior[1](/* Pass objects, values */);
return yield next;
}
];
app.use(...middleware);
USING PROMISES WITH MOCHA
We need:
• A test framework syntax that facilitates easy async testing.
(Supported natively in Mocha since 1.18.0)
• An assertion syntax that we are familiar with. (Assert)
• A set of assertions that facilitate easily writing tests of
promises. (assertPromise)
express
USING PROMISES WITH
MOCHA (ASSERT_PROMISE)
Old Paradigm
New Paradigm
express
describe('behavior', () => {
it ('resolves under condition X with result Y', (done) => {
behavior().then(function (done) {
/* Assert here. */
}).finally(done);
});
});
import {assertPromise} from 'assert-promise';
describe('behavior', () => {
it ('resolves under condition X with result Y', () => {
return assertPromise.equal(behavior(), 'value');
});
});
USING GENERATORS WITH MOCHA
We need:
• Use the same async flow that Koa leverages (ES15 generators
and co)
• An assertion syntax that we are familiar with. (Assert)
• Mocha syntax that facilitates easily writing tests of generators
with co. (co-mocha)
CO-MOCHA
Enable support for generators in Mocha tests using co.
https://www.npmjs.com/package/co-mocha
USING PROMISES WITH
MOCHA (CO-MOCHA)
Old Paradigm
(No Co-Mocha)
New Paradigm
describe('behavior', () => {
it ('resolves under condition X with result Y', (done) => {
behavior().then(function () {
/* Assert here. */
}).finally(done);
});
});
describe('behavior', () => {
it ('resolves under condition X with result Y', function* () {
return Assert.equal(yield behavior(), 'value');
});
});
PUTTING IT ALLTOGETHER
“Detroit Industry” by Diego Rivera
Return Client-Server
Interaction to Endpoints
ENDPOINTS
Pull Behavior
into Endpoint
import {behavior} from './behavior.js';
app.use(function (req, res, next) {
behavior()
.then(function () { next(); })
.catch(res.json)
});
express
Use Promise as
Flow Control
BEHAVIOR
export function behavior (req, res, next) {
return new Promise(function (resolve, reject) {
/* Define behavior and resolve or reject. */
}
};
express
Pull Behavior IntoTests
TEST
Use Promises with Mochaimport {assertPromise} from "assert-promise";
var behavior = require('./behavior.js');
describe('behavior', () => {
it ('resolves under condition X with result Y', () => {
return assertPromise.equal(behavior(), 'value');
});
});
express
Return Client-Server
Interaction to Endpoints
ENDPOINTS
Pull Behavior
into Endpoint
import {behavior} from './behavior.js';
app.use(function* (next) {
let message = yield behavior();
this.body = message;
});
Use Generators as
Flow Control
BEHAVIOR
export function* behavior (next) {
yield asyncRequest();
return yield next;
};
Pull Behavior IntoTests
TEST
var behavior = require('./behavior.js');
describe('behavior', () => {
it ('resolves under condition X with result Y', function* () {
return Assert.equal(yield behavior(), 'value');
});
});
QUESTIONS
GET INTOUCH
! @morrissinger
" linkedin.com/in/morrissinger
# morrissinger.com
$ github.com/morrissinger

More Related Content

What's hot

ppt of web designing and development
ppt of web designing and developmentppt of web designing and development
ppt of web designing and development47ishu
 
HTML Introduction, HTML History, HTML Uses, HTML benifits
HTML Introduction, HTML History, HTML Uses, HTML benifitsHTML Introduction, HTML History, HTML Uses, HTML benifits
HTML Introduction, HTML History, HTML Uses, HTML benifitsPro Guide
 
HTML + CSS Examples
HTML + CSS ExamplesHTML + CSS Examples
HTML + CSS ExamplesMohamed Loey
 
Installation guide for mysql in windows
Installation guide for mysql in windowsInstallation guide for mysql in windows
Installation guide for mysql in windowssharavanakumar10
 
WEB I - 01 - Introduction to Web Development
WEB I - 01 - Introduction to Web DevelopmentWEB I - 01 - Introduction to Web Development
WEB I - 01 - Introduction to Web DevelopmentRandy Connolly
 
Linux.ppt
Linux.ppt Linux.ppt
Linux.ppt onu9
 
Linux operating system ppt
Linux operating system pptLinux operating system ppt
Linux operating system pptAchyut Sinha
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation Salman Memon
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An IntroductionManvendra Singh
 
Introduction to xampp
Introduction to xamppIntroduction to xampp
Introduction to xamppJin Castor
 
Introduction to java netbeans
Introduction to java netbeansIntroduction to java netbeans
Introduction to java netbeansShrey Goswami
 

What's hot (20)

ppt of web designing and development
ppt of web designing and developmentppt of web designing and development
ppt of web designing and development
 
HTML Introduction, HTML History, HTML Uses, HTML benifits
HTML Introduction, HTML History, HTML Uses, HTML benifitsHTML Introduction, HTML History, HTML Uses, HTML benifits
HTML Introduction, HTML History, HTML Uses, HTML benifits
 
CSS Basics
CSS BasicsCSS Basics
CSS Basics
 
HTML + CSS Examples
HTML + CSS ExamplesHTML + CSS Examples
HTML + CSS Examples
 
Installation guide for mysql in windows
Installation guide for mysql in windowsInstallation guide for mysql in windows
Installation guide for mysql in windows
 
WEB I - 01 - Introduction to Web Development
WEB I - 01 - Introduction to Web DevelopmentWEB I - 01 - Introduction to Web Development
WEB I - 01 - Introduction to Web Development
 
Linux.ppt
Linux.ppt Linux.ppt
Linux.ppt
 
Linux operating system ppt
Linux operating system pptLinux operating system ppt
Linux operating system ppt
 
Complete Lecture on Css presentation
Complete Lecture on Css presentation Complete Lecture on Css presentation
Complete Lecture on Css presentation
 
Introduction to linux
Introduction to linuxIntroduction to linux
Introduction to linux
 
Introduction to Web development
Introduction to Web developmentIntroduction to Web development
Introduction to Web development
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An Introduction
 
Introduction to xampp
Introduction to xamppIntroduction to xampp
Introduction to xampp
 
Wordpress
WordpressWordpress
Wordpress
 
Report html5
Report html5Report html5
Report html5
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
CSS
CSSCSS
CSS
 
Introduction to java netbeans
Introduction to java netbeansIntroduction to java netbeans
Introduction to java netbeans
 
Js ppt
Js pptJs ppt
Js ppt
 
Cgi
CgiCgi
Cgi
 

Similar to Unit Testing Express and Koa Middleware in ES2015

Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express MiddlewareMorris Singer
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.jsdavidchubbs
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013Laurent_VB
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express Jeetendra singh
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Codemotion
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Visual Engineering
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Module design pattern i.e. express js
Module design pattern i.e. express jsModule design pattern i.e. express js
Module design pattern i.e. express jsAhmed Assaf
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications Juliana Lucena
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascriptEldar Djafarov
 
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...apidays
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETGianluca Carucci
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingVisual Engineering
 

Similar to Unit Testing Express and Koa Middleware in ES2015 (20)

Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express Middleware
 
Middleware.pdf
Middleware.pdfMiddleware.pdf
Middleware.pdf
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Module design pattern i.e. express js
Module design pattern i.e. express jsModule design pattern i.e. express js
Module design pattern i.e. express js
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
 
Intro to Node
Intro to NodeIntro to Node
Intro to Node
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
 
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...
apidays LIVE Australia 2020 - Building distributed systems on the shoulders o...
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 

Recently uploaded

%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedDelhi Call girls
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456KiaraTiradoMicha
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ
 

Recently uploaded (20)

%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 

Unit Testing Express and Koa Middleware in ES2015

  • 1. UNITTESTING NODE.JS MIDDLEWARE By Morris Singer This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. express and ES15 Edition!
  • 2. ABOUT ME • Senior Software Engineer atVerilume • I Like: • Test-Driven Development • Angular 1 and 2,Aurelia, Ionic, and React.js, Node.js, and Cordova
  • 3. AGENDA • Define middleware and why it isn’t just a fancy term for controllers or endpoints. • Review behavior-driven development principles for unit testing. • Argue why middleware are behavioral units. • Summarize common challenges testing behavior in Express and Koa. • Learn and implement a pattern for Express and Koa Middleware. • Answer questions. (10 minutes)
  • 5. A SIMPLE CASE One Middleware Per Endpoint express app.use(function (req, res, next) { res.send('hello world'); });
  • 6. A SIMPLE CASE “Why is it called ‘Middleware’ anyway?” app.use(function* (next) { this.body = 'hello world'; }); • One Middleware Per Endpoint
  • 7. MORE COMPLEX CASES Two Ways of Stacking Middleware Variadic Iterative express const middleware = [ function (req, res, next) { req.message = 'HELLO WORLD'; next(); }, function (req, res, next) { res.send(req.message.toLowerCase()); } ]; middleware.forEach(app.use);app.use(...middleware);
  • 8. MORE COMPLEX CASES Two Ways of Stacking Middleware Variadic Iterative app.use(...middleware); const middleware = [ function* (next) => { this.message = 'HELLO WORLD'; return yield next; }, function* (next) => { this.body = this.message.toLowerCase(); } ]; middleware.forEach(app.use);
  • 9. THE MIDDLEWARE STACK GET Done Generate Message Send Lowercase Message express app.use( function (req, res, next) { req.message = 'HELLO WORLD'; next(); }, function (req, res, next) { res.send(req.message.toLowerCase()); } );
  • 10. THE MIDDLEWARE STACK GET Done Generate Message Assign Lowercase to Body app.use( function (next) { this.message = 'HELLO WORLD'; return yield next; }, function (next) { this.body = this.message.toLowerCase(); } );
  • 11. A B C 1 D E F 2 G H I 3 GET /
  • 13. COMMON CHALLENGES Or,Why Node Developers Often AvoidTDD
  • 14. HTTP RESPONSETESTS What happens when we add a middleware to the stack? express it('should return a 500 error', (done) => { request({ method: 'POST', url: 'http://localhost:3000/api/endpoint' }, (error, response, body) => { Assert.equal(response.statusCode, 500); done(); }); });
  • 15. TESTING MID-STACK How do we pull out these anonymous functions? express const middleware = [ function (req, res, next) { req.message = 'HELLO WORLD'; next(); }, function (req, res, next) { res.send(req.message.toLowerCase()); } ]; middleware.forEach(app.use);
  • 16. ILLUMINATINGTEST FAILURES What happens if next() is not called? express import {httpMocks} from 'node-mocks-http'; it('should call next()', (done) => { var req = httpMocks.createRequest(), res = httpMocks.createResponse(); middleware(req, res, () => { done(); }); });
  • 17. KNOWING WHENTOTEST When is the assertion run? express import {httpMocks} from 'node-mocks-http'; it('should call next()', () => { var req = httpMocks.createRequest(), res = httpMocks.createResponse(); middleware(req, res); return Assert.equal(req.foo, 'bar'); });
  • 18. TESTING WITH DATA Where do data come from? express app.get('path/to/post', function (req, res, next) { Post.findOne(params).exec(function (err, post) { res.json(post); }); });
  • 19. DEALING WITH POLLUTION How does one reset the data? express it('should update the first post', () => { /* ... */ }); it('should get the first post', () => { /* ... */ });
  • 20. MOCKING DEPENDENCIES How does one cut out the external data source? express app.get('endpoint', function (req, res, next) { request({ method: 'GET', url: 'http://example.com/api/call' }, (error, response, body) => { req.externalData = body; next(); }); });
  • 21. MIDDLEWARE + SEPARATION OF CONCERNS + FLOW CONTROL The “Eureka” Moment
  • 22. OVERVIEW • Pull behavior into middleware and tests. • Use promises or generators as flow control. • Return client-server interaction to endpoint. • Use promises or generators with Mocha.
  • 24. PULL BEHAVIOR INTO ENDPOINTS Old Paradigm New Paradigm N.B.:This only looks like a lot more code… express const middleware = [ function (req, res, next) { /* Behavior */ }, function (req, res, next) { /* Behavior */ } ]; app.use(...middleware); const behavior = { first: function () {}, second: function () {} }; const middleware = [ function (req, res, next) { behavior.first(); next(); }, function (req, res, next) { behavior.second(); next(); } ]; app.use(...middleware);
  • 25. PULL BEHAVIOR INTO ENDPOINTS Old Paradigm New Paradigm const middleware = [ function* (next) { /* Behavior */ }, function* (next) { /* Behavior */ } ]; app.use(...middleware); const behavior = { first: function* () {}, second: function* () {} }; const middleware = [ function* (next) { yield behavior.first(); return yield next; }, function* (next) { yield behavior.second(); return next; } ]; app.use(...middleware);
  • 26. USE PROMISES AS FLOW CONTROL • Clean, standardized interface between asynchronous behavior and endpoints. • Both endpoints and tests can leverage the same mechanism in the behavior for serializing logic. express
  • 27. USE PROMISES AS FLOW CONTROL Old Paradigm New Paradigm express export function middleware (req, res, next) { /* Define behavior and call res.json(), next(), etc. */ }; export function behavior () { return new Promise((resolve, reject) => { /* Define behavior and resolve or reject promise. */ }; }
  • 28. USE GENERATORS (WITH CO) AS FLOW CONTROL • Same interface between asynchronous behavior and middleware as already used between successive middleware. • Both endpoints and tests can leverage the same mechanism in the behavior for serializing logic.
  • 29. CO Generator based control flow goodness for nodejs and the browser, using promises, letting you write non-blocking code in a nice-ish way. https://www.npmjs.com/package/co
  • 30. USE GENERATORS AS LINK BETWEEN MIDDLEWARE AND ENDPOINTS Old Paradigm New Paradigm export function* middleware (next) { /* Call with assigned context and leverage behavior on the Koa context, yield next, etc.*/ }; export function* behavior () { /* Define behavior and yield values. */ }
  • 32. RETURN CLIENT-SERVER INTERACTIONTO ENDPOINT Old Paradigm New Paradigm express const middleware = [ function (req, res, next) {}, function (req, res, next) {} ]; app.use(...middleware); const behavior = [ function () {}, function () {} ]; const middleware = [ function (req, res, next) { behavior[0](/* Pass objects, values */) .then(function () { next(); }) .catch(res.json); }, function (req, res, next) { behavior[1](/* Pass objects, values */) .then(function () { next(); }) .catch(res.json); } ]; app.use(...middleware);
  • 33. RETURN CLIENT-SERVER INTERACTIONTO ENDPOINT Old Paradigm New Paradigm express const middleware = [ function (req, res, next) {}, function (req, res, next) {} ]; app.use(...middleware); const behavior = [ function () {}, function () {} ]; const middleware = behavior.map((func) => { return function (req, res, next) { func() .then(function () { next(); }) .catch(res.json); } }; app.use(...middleware);
  • 34. RETURN CLIENT-SERVER INTERACTIONTO ENDPOINT Old Paradigm New Paradigm express const middleware = [ function (req, res, next) {}, function (req, res, next) {} ]; app.use(...middleware); const behavior = [ function () {}, function () {} ]; const middleware = behavior.map((func) => { return function(args) { return function (req, res, next) { func() .then(function () { next(); }) .catch(res.json); } } }; app.use( middleware[0](/* Pass objects, values */), middleware[1](/* Pass objects, values */) );
  • 35. RETURN CLIENT-SERVER INTERACTIONTO ENDPOINT Old Paradigm New Paradigm const middleware = [ function* (next) {}, function* (next) {} ]; app.use(...middleware); const behavior = [ function* () {}, function* () {} ]; const middleware = [ function* (next) { yield behavior[0](/* Pass objects, values */); return yield next; }, function* (next) { yield behavior[1](/* Pass objects, values */); return yield next; } ]; app.use(...middleware);
  • 36. USING PROMISES WITH MOCHA We need: • A test framework syntax that facilitates easy async testing. (Supported natively in Mocha since 1.18.0) • An assertion syntax that we are familiar with. (Assert) • A set of assertions that facilitate easily writing tests of promises. (assertPromise) express
  • 37. USING PROMISES WITH MOCHA (ASSERT_PROMISE) Old Paradigm New Paradigm express describe('behavior', () => { it ('resolves under condition X with result Y', (done) => { behavior().then(function (done) { /* Assert here. */ }).finally(done); }); }); import {assertPromise} from 'assert-promise'; describe('behavior', () => { it ('resolves under condition X with result Y', () => { return assertPromise.equal(behavior(), 'value'); }); });
  • 38. USING GENERATORS WITH MOCHA We need: • Use the same async flow that Koa leverages (ES15 generators and co) • An assertion syntax that we are familiar with. (Assert) • Mocha syntax that facilitates easily writing tests of generators with co. (co-mocha)
  • 39. CO-MOCHA Enable support for generators in Mocha tests using co. https://www.npmjs.com/package/co-mocha
  • 40. USING PROMISES WITH MOCHA (CO-MOCHA) Old Paradigm (No Co-Mocha) New Paradigm describe('behavior', () => { it ('resolves under condition X with result Y', (done) => { behavior().then(function () { /* Assert here. */ }).finally(done); }); }); describe('behavior', () => { it ('resolves under condition X with result Y', function* () { return Assert.equal(yield behavior(), 'value'); }); });
  • 41. PUTTING IT ALLTOGETHER “Detroit Industry” by Diego Rivera
  • 42. Return Client-Server Interaction to Endpoints ENDPOINTS Pull Behavior into Endpoint import {behavior} from './behavior.js'; app.use(function (req, res, next) { behavior() .then(function () { next(); }) .catch(res.json) }); express
  • 43. Use Promise as Flow Control BEHAVIOR export function behavior (req, res, next) { return new Promise(function (resolve, reject) { /* Define behavior and resolve or reject. */ } }; express
  • 44. Pull Behavior IntoTests TEST Use Promises with Mochaimport {assertPromise} from "assert-promise"; var behavior = require('./behavior.js'); describe('behavior', () => { it ('resolves under condition X with result Y', () => { return assertPromise.equal(behavior(), 'value'); }); }); express
  • 45. Return Client-Server Interaction to Endpoints ENDPOINTS Pull Behavior into Endpoint import {behavior} from './behavior.js'; app.use(function* (next) { let message = yield behavior(); this.body = message; });
  • 46. Use Generators as Flow Control BEHAVIOR export function* behavior (next) { yield asyncRequest(); return yield next; };
  • 47. Pull Behavior IntoTests TEST var behavior = require('./behavior.js'); describe('behavior', () => { it ('resolves under condition X with result Y', function* () { return Assert.equal(yield behavior(), 'value'); }); });
  • 49. GET INTOUCH ! @morrissinger " linkedin.com/in/morrissinger # morrissinger.com $ github.com/morrissinger