首页 > 解决方案 > InversifyJS 联合测试 sinon stub

问题描述

我正在尝试在我的InversifyJS项目上编写单元测试代码。路线测试(使用supertest)工作正常。然后尝试编写sinon stubspy测试,但无法成功。我的示例代码如下:

演示路线

@injectable()
class DemoRoute implements IDemoRoute {
 private _demoController:IDemoController;

 constructor( @inject(TYPES.IDemoController) demoController:IDemoController ) {
   this._demoController = demoController;
 }

 create(req: Request, res: Response, next: NextFunction) {
   return this._demoController.create(req.body)
 }
}

演示.test.ts

import "reflect-metadata";
import * as sinon from "sinon";
const sandbox = sinon.createSandbox();

describe.only("Demo Spec 2", () => {
   demoController = container.get<IDemoController>(TYPES.IDemoController);

   beforeEach((done) => {
      insertStub = sandbox.stub(demoController, 'create');
      done();
   });

   afterEach(() => {
     sandbox.restore();
   });

   it("Should call demo route url", async done => {
     demoRoute  = container.get<IDemoRoute>(TYPES.IDemoRoute);
     const stub =  insertStub.returns(Promise.resolve({ body: { name: "test xyz", code: "test abc"} }));
     const result = await demoRoute.create({body: demoData.validData}, {send: (params) => params});
     expect(stub).to.have.been.called; // throw error
     done();
   });
}

单元测试出错

UnhandledPromiseRejectionWarning: AssertionError: 预期 create 至少被调用过一次,但它从未被调用过

我怎么解决这个问题?提前致谢。

标签: node.jsunit-testingsinonsinon-chaiinversifyjs

解决方案


我们能够通过对从 inversify 容器中提取的实例的方法进行存根,并使用sinon.createStubInstance()模拟构造函数来使存根工作。看起来像这样:

describe.only("Demo Spec 2", () => {
   demoController = container.get<IDemoController>(TYPES.IDemoController);
   demoControllerStub = sinon.createStubInstance(IDemoController) as SinonStubbedInstance<IDemoController>;
   beforeEach((done) => {
      insertStub = sinon.stub(demoController, 'create');
      done();
   });

   afterEach(() => {
     sandbox.restore();
   });

   it("Should call demo route url", async done => {
     demoRoute  = container.get<IDemoRoute>(TYPES.IDemoRoute);
     const stub =  insertStub.returns(Promise.resolve({ body: { name: "test xyz", code: "test abc"} }));
     const result = await demoRoute.create({body: demoData.validData}, {send: (params) => params});
     expect(demoControllerStub.create.calledOnce);
     done();
   });
}

我更喜欢的另一种对我们有用的方法是存根实例并取消绑定并将存根实例绑定到容器。看起来像这样:

describe.only("Demo Spec 2", () => {
   demoControllerStub = sinon.createStubInstance(IDemoController);

   container.unbind(IDemoController);
   container.bind(IDemoController).toConstantValue(demoControllerStub);

   beforeEach((done) => {
      demoControllerStub.create.reset();
      done();
   });

   it("Should call demo route url", async done => {
     demoRoute  = container.get<IDemoRoute>(TYPES.IDemoRoute);
     const stub =  insertStub.returns(Promise.resolve({ body: { name: "test xyz", code: "test abc"} }));
     const result = await demoRoute.create({body: demoData.validData}, {send: (params) => params});
     sinon.assert.calledWith(demoControllerStub.create, sinon.match({body: demoData.validData});
     done();
   });
}


推荐阅读