简体   繁体   English

单元测试表达路由器

[英]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: 我想测试我的通用路由器,但我看到一些问题:

  1. How to "inject" the app? 如何“注入”应用程序? I could create an instance of Express ( 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? 获得适当模拟的最佳方法是什么?
  2. What exactly should I test? 我到底应该测试什么? As far as I see my router itself (without integration) isn't doing anything else but console output (not worth to test) and a call of a function ( controller.create(req, res); ). 据我所知,我的路由器本身(没有集成)除了控制台输出(不值得测试)和函数调用( controller.create(req, res); )之外没有做任何其他事情。 How should I test if this function is called? 如何测试是否调用此函数? Or is there anything else to test? 还是还有其他要测试的东西吗?
  1. You should probably make a stub implementation of app. 你应该做一个app的存根实现。

  2. 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存根放入您的应用程序存根中,然后在测试中检查它们是否使用预期参数调用。

  1. I would use jasmine.createSpyObj to mock app (and maybe controller as well). 我会使用jasmine.createSpyObj来模拟应用程序(也可能是控制器)。
  2. I think you just need to test that app.post gets called with the arguments '/api/' + resourceName and controller.create, because you aren't testing that express.post works correctly or not. 我想你只需要测试app.post被调用参数'/ api /'+ resourceName和controller.create,因为你没有测试express.post是否正常工作。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM