I don't know how I'd term this maybe 'static call to a koa router'? Does that seem like the right wordage here for what I'm really trying to accomplish if you were to talk about it technically?
Anyway, I'm using koa-router and I'm coding unit tests (not integration tests). So I do not want to invoke .listen() on my koa app because of that reason...it would create an http server which now makes my test an integration tests.
Instead in my test I simply want to make a straight call to the app object instance and call a route and be able to return no results and check that I returned no results in the response.
How can you do that? I can't find an example and I've tried all sorts of pseudo code attemps agains the koa app object.
Koa is a new web framework designed by the team behind Express, which aims to be a smaller, more expressive, and more robust foundation for web applications and APIs. By leveraging async functions, Koa allows you to ditch callbacks and greatly increase error-handling.
If you want to test the function that koa-router routes to then just perform a unit test on that function and leave the routing out of it.
To me it sounds like you've got a file such as app.js and it contains all your code. What you can do is create a router.js file to put you route bindings and a services.js file where you can put your application logic.
So for example app.js might look like:
var koa = require("koa");
var app = module.exports = koa();
var router = require('./router.js');
app.use(router.unsecured.middleware());
app.listen(3000);
And router.js might look like:
var router = require("koa-router");
var service = require("./services.js");
var unsecured = module.exports.unsecured = new router();
unsecured.post('/account/signin', service.signinUser);
unsecured.post('/account/register', service.registerUser);
And services.js might look like:
module.exports.signinUser = function*(signinDetails) {
// contains your application signin logic
};
module.exports.registerUser = function*(registerDetails) {
// contains your application register logic
};
So in this manner you can individually test services.js. I don't see any value in individually testing router.js since it is so trivial. As @Dan Pantry shows you can test routing as part of an integration test using supertest.
Edit:
So this is a little experimental test I was playing around with to test that the routing is correct. I'm using mocha as the test runner and the code example I posted in my original code.
// standard library
var assert = require("assert");
// in app objects
var router = require('./router.js');
var service = require('./service.js');
describe("routing tests", function() {
it("test register routing, POST", function*(done) {
// arrange
var unsecured = router.unsecured;
var path = '/account/register';
var httpMethod = 'POST';
var expected = service.register.toString();
var actual;
// act
for (var i = 0; i < unsecured.stack.length; i++)
{
var pathMatch = unsecured.stack[i].path === path;
var methodMatch = unsecured.stack[i].methods.indexOf(httpMethod) >= 0;
if (pathMatch && methodMatch)
{
actual = unsecured.stack[i].middleware.toString();
break;
}
}
// assert
try {
assert.equal(expected, actual);
done();
} catch(err) {
done(err);
}
});
});
There is probably a neater way of doing this (and a more modular way for testing multiple paths) but as I said this is just a basic example to verify the routing is calling the correct service. What I'm doing is delving into the koa-router object to verify what path is bound to what service code depending on the HTTP method (e.g. POST, GET, etc).
If you have your routing and your services in modules this test completely avoids dealing with the main koa app. Although technically this test spans multiple units (the routing and the service code) so it would technically be an integration test but it does mean you don't go near app.listen()
which is what you didn't want to call in your tests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With