用Sinon存根testing快速路线

我试图unit testingExpress路线来validation他们调用正确的控制器function。 在这一点上,我没有检查控制器function的内部逻辑,只是路由映射到正确的function。 到目前为止,我已经完美地工作了,直到我引入路由器中间件如此:

'use strict'; import express from 'express'; import config from './../../config/environments'; import SuperLogin from 'superlogin'; let controller = require('./subjects.controller'); let router = express.Router(); let superlogin = new SuperLogin(config); router.get('/', superlogin.requireAuth, superlogin.requireAnyRole(['admin', 'specialist', 'nurse']), controller.index); router.get('/:subjectId', superlogin.requireAuth, superlogin.requireAnyRole(['admin', 'specialist', 'nurse']), controller.show); router.post('/', superlogin.requireAuth, superlogin.requireAnyRole(['admin', 'specialist', 'nurse']), controller.create); router.put('/:subjectId', superlogin.requireAuth, superlogin.requireAnyRole(['admin', 'specialist', 'nurse']), controller.upsert); router.patch('/:subjectId', superlogin.requireAuth, superlogin.requireAnyRole(['admin', 'specialist', 'nurse']), controller.patch); router.delete('/:subjectId', superlogin.requireAuth, superlogin.requireAnyRole(['admin']), controller.destroy); module.exports = router; 

正如你所看到的,我使用Superlogin来validation每条路线的访问权限。 如果我删除了这个testing,那么添加中间件会导致失败。 我可能需要存根superlogin方法,但我不知道在哪里做这个。

我的testing如下

 'use strict'; /* globals sinon, describe, expect, it */ let proxyquire = require('proxyquire').noPreserveCache(); let subjectCtrlStub = { index: 'subjectCtrl.index', show: 'subjectCtrl.show', create: 'subjectCtrl.create', upsert: 'subjectCtrl.upsert', patch: 'subjectCtrl.patch', destroy: 'subjectCtrl.destroy' }; sinon.stub(superlogin, 'requireAuth', function(req, res, next) { return next(); }); let routerStub = { get: sinon.spy(), put: sinon.spy(), patch: sinon.spy(), post: sinon.spy(), delete: sinon.spy() }; // require the index with our stubbed out modules let subjectRoutes = proxyquire('./subjects.routes.js', { express: { Router() { return routerStub; } }, './subjects.controller': subjectCtrlStub }); describe('Subject API Router:', function() { it('should return an express router instance', function() { subjectRoutes.should.equal(routerStub); }); describe('GET /api/subjects', function() { it('should route to subjects.controller.index', function() { routerStub.get .withArgs('/', 'subjectCtrl.index') .should.have.been.calledOnce; }); }); describe('GET /api/subjects/:subjectId', function() { it('should route to subjects.controller.show', function() { routerStub.get .withArgs('/:subjectId', 'subjectCtrl.show') .should.have.been.calledOnce; }); }); describe('POST /api/subjects', function() { it('should route to subjects.controller.create', function() { routerStub.post .withArgs('/', 'subjectCtrl.create') .should.have.been.calledOnce; }); }); describe('PUT /api/subjects/:subjectId', function() { it('should route to subjects.controller.upsert', function() { routerStub.put .withArgs('/:subjectId', 'subjectCtrl.upsert') .should.have.been.calledOnce; }); }); describe('PATCH /api/subjects/:subjectId', function() { it('should route to subjects.controller.patch', function() { routerStub.patch .withArgs('/:subjectId', 'subjectCtrl.patch') .should.have.been.calledOnce; }); }); describe('DELETE /api/subjects/:subjectId', function() { it('should route to subjects.controller.destroy', function() { routerStub.delete .withArgs('/:subjectId', 'subjectCtrl.destroy') .should.have.been.calledOnce; }); }); }); 

我有一个before函数在所有这些testing之前运行,这些testing用具有不同angular色的一些示例用户种子数据库,并将授权令牌保存到全局variables以用于testing端点时,我只是不知道如何发送它们routerStub函数调用。

使用存根提供已知值的SUT的直接input或不正确的input

您可能会考虑事实的确认,在某些情况下应该从路由中可以获得什么样的视图函数。 在这种情况下,使用存根为中间件提供影响其行为的input数据(例如,用于身份validation的用户凭证)。 不要用stubs替代中间件本身,因为如果stub完全改变行为,这样的testing将是无关紧要的。