[英]Unit testing express routers
I know this has been discussed a couple of times. 我知道这已经讨论了几次。 Anyway, I feel like all the provided solutions don't (perfectly) fit to my requirement(s). 无论如何,我觉得所有提供的解决方案都不能(完全)符合我的要求。 I have the following code: 我有以下代码:
router.js:
------------------
var Router = function(app, resourceName, controller) {
//Create
app.post('/api/' + resourceName, function(req, res) {
console.log('Incoming request: ' + resourceName + ' (POST)');
controller.create(req, res);
});
};
module.exports = Router;
As you can see this is a very "generic" router. 如您所见,这是一个非常“通用”的路由器。 It can be instantiated for example in the server like this: 它可以在服务器中实例化,如下所示:
var app = express();
var userController = ...
var userRouter = new Router(app, 'Users', userController);
So I don't have to write a file per resource but I just have one generic router. 所以我不必为每个资源编写一个文件,但我只有一个通用路由器。
I would like to test my generic router but I see some problems: 我想测试我的通用路由器,但我看到一些问题:
var app = express();
) but I think a mock would be better (as this is a unit test, not an integration test!). 我可以创建一个Express实例( var app = express();
)但我认为模拟会更好(因为这是一个单元测试,而不是集成测试!)。 What's the best way to get an appropriate mock? 获得适当模拟的最佳方法是什么? controller.create(req, res);
). 据我所知,我的路由器本身(没有集成)除了控制台输出(不值得测试)和函数调用( controller.create(req, res);
)之外没有做任何其他事情。 How should I test if this function is called? 如何测试是否调用此函数? Or is there anything else to test? 还是还有其他要测试的东西吗? You should probably make a stub implementation of app. 你应该做一个app的存根实现。
What you want to test is that the constructor registers listeners on specified routes + HTTP methods. 您要测试的是构造函数在指定的路由上注册侦听器+ HTTP方法。 I would advise putting Sinon.js stubs into your app stub, and then in your tests check that they are called with expected arguments. 我建议将Sinon.js存根放入您的应用程序存根中,然后在测试中检查它们是否使用预期参数调用。
Here's how I'd do those two things specifically. 这是我如何具体做这两件事。
I'd modify router.js a little bit to make this easier: 我会稍微修改router.js以使这更容易:
var Router = function(app, resourceName, controller) {
app.post('/api/' + resourceName, controller.create.bind(controller))
}
module.exports = Router;
And then the test would look like this: 然后测试看起来像这样:
describe("Router", function() {
it("should route /api to controller.create", function() {
router = require('./router');
app = jasmine.createSpyObj('application', ['post']);
controller = jasmine.createSpyObj('controller', ['create']);
router(app, 'foo', controller);
expect(app.post).toHaveBeenCalledWith('/api/foo', jasmine.any(Function));
});
});
This isn't a perfect test because it isn't actually checking that controller.create specifically is getting called. 这不是一个完美的测试,因为它实际上并没有检查control.create是否被调用。 That gets a little more complicated because of the .bind() stuff. 由于.bind()的东西,这会变得有点复杂。
describe("Router", function() {
it("should route /api to controller.create", function() {
router = require('./router');
app = jasmine.createSpyObj('application', ['post']);
controller = jasmine.createSpyObj('controller', ['create']);
controller.create = jasmine.createSpyObj('binder', ['bind']);
controller.create.bind.and.returnValue('bar');
router(app, 'foo', controller);
expect(controller.create.bind).toHaveBeenCalledWith(controller);
expect(app.post).toHaveBeenCalledWith('/api/foo', controller.create.bind(controller));
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.