如何模拟在函数内部实例化的类 - Sinon?

Har*_*han 1 unit-testing mocking express sinon typescript

假设我有一个像follow这样的功能。

import NetworkService from './services';

async function sendAPIRequest(data: any){
  // validations
  const service = new NetworkService();
  await service.call(data)
}
Run Code Online (Sandbox Code Playgroud)

我的测试看起来像这样,它使用了 mocha、chai、sinon。

describe('sendAPIRequest', function(){
   it('make api', async function(){

       // trying to mock Network service like below
       const serviceMock = sinon.createStubInstance(NetworkService);
       await sendAPIRequest({name: 'foobar'})
   });
});
Run Code Online (Sandbox Code Playgroud)

但我收到了类似的错误

错误:预期在对象上存根方法,但没有找到

NetworkService.测试时如何模拟我的sendAPIRequest.

sli*_*wp2 6

sinon.createStubInstance()API 不会用存根call方法替换导入的原始方法NetworkService。它只是创建一个存根实例,因此您需要将此存根实例传递给您sendAPIRequest并使用它。这意味着您应该将其用作依赖注入模式。

有两种方法可以测试您的代码:

  1. 存根中的call方法NetworkService.prototype

index.ts

import NetworkService from "./services";

export async function sendAPIRequest(data: any) {
  const service = new NetworkService();
  await service.call(data);
}
Run Code Online (Sandbox Code Playgroud)

services.ts

export default class NetworkService {
  public async call(data) {
    return "real implementation";
  }
}
Run Code Online (Sandbox Code Playgroud)

index.test.ts

import sinon from "sinon";
import NetworkService from "./services";
import { sendAPIRequest } from "./";

describe("sendAPIRequest", function() {
  afterEach(() => {
    sinon.restore();
  });

  it("should make api", async () => {
    const callStub = sinon.stub(NetworkService.prototype, "call");
    await sendAPIRequest({ name: "foobar" });
    sinon.assert.calledWithExactly(callStub, { name: "foobar" });
  });
});
Run Code Online (Sandbox Code Playgroud)

带有覆盖率报告的单元测试结果:

 sendAPIRequest
    ? should make api


  1 passing (12ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |       95 |      100 |    83.33 |    94.44 |                   |
 index.test.ts |      100 |      100 |      100 |      100 |                   |
 index.ts      |      100 |      100 |      100 |      100 |                   |
 services.ts   |       75 |      100 |       50 |       75 |                 3 |
---------------|----------|----------|----------|----------|-------------------|
Run Code Online (Sandbox Code Playgroud)
  1. 使用proxyquire模块

index.test.ts

import proxyquire from "proxyquire";
import sinon from "sinon";

describe("sendAPIRequest", function() {
  afterEach(() => {
    sinon.restore();
  });

  it("make api", async function() {
    const networkServiceInstanceStub = {
      call: sinon.stub(),
    };
    const NetworkServiceStub = sinon.stub().callsFake(() => networkServiceInstanceStub);
    const { sendAPIRequest } = proxyquire("./", {
      "./services": {
        default: NetworkServiceStub,
      },
    });
    await sendAPIRequest({ name: "foobar" });
    sinon.assert.calledOnce(NetworkServiceStub);
    sinon.assert.calledWithExactly(networkServiceInstanceStub.call, { name: "foobar" });
  });
});
Run Code Online (Sandbox Code Playgroud)

带有覆盖率报告的单元测试结果:

  sendAPIRequest
    ? make api (279ms)


  1 passing (286ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |    95.24 |      100 |    85.71 |       95 |                   |
 index.test.ts |      100 |      100 |      100 |      100 |                   |
 index.ts      |      100 |      100 |      100 |      100 |                   |
 services.ts   |       75 |      100 |       50 |       75 |                 3 |
---------------|----------|----------|----------|----------|-------------------|
Run Code Online (Sandbox Code Playgroud)

相关帖子:

源代码:https : //github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59897060

  • 谢谢,它可以工作,但是如果“NetworkService”中的“call”方法是一个“箭头”函数,它会抛出“无法存根不存在的自己的属性调用”,因为它将在对象创建中可用,是否有任何解决方法? (2认同)