【问题标题】:Problem stubbing a class method with Sinon使用 Sinon 存根类方法的问题
【发布时间】:2021-04-10 02:23:22
【问题描述】:

我有一个具有以下类的 NodeJS + Typescript 应用程序:

export default class OrderStreamWriter {
  private readonly redis: IORedis;
  private readonly orderStream: string;
  private readonly logger: LoggerFactory;

  constructor(redisHost: string, redisPort: number, redisPass: string, orderStream: string) {
    this.orderStream = orderStream;

    this.redis = createRedisClient(redisHost, redisPort, redisPass);
    this.logger = new LoggerFactory('streams/OrderStreamWriter');
  }

  public async write(msg: string): Promise<void> {
    await this.redis.xadd(this.orderStream, '*', 'trade', msg).catch((err: Error) => {
      this.logger.log(
        `Error Writing message to stream (${this.orderStream}): ${err.message}. Quitting...`,
      );
      process.exit(1);
    });
  }
}

在另一个类中,我使用write 方法将结果写入Redis 流。 我想在不调用实际的 write 函数的情况下测试该流程,而只是检查该函数是否会使用某些参数被调用,这是我的测试(使用 mocha + sinon 运行):

  it('process the input and return an order', () => {
    const rule = directOrder[0].rule;
    const user = directOrder[0].user;
    //const writeStub = sinon.stub(OrderStreamWriter.prototype, "write");
    const Writer: any = sinon.stub();
    sinon.stub(Writer.prototype, "write");
    const writer = new Writer();
    const order = {}

    // console.log(writeStub)
    const directTriggerStrategy: TriggerContext = new TriggerContext(user, rule, writer);
    directTriggerStrategy.execute()

    sinon.assert.calledWithExactly(writer, order);
  })

使用当前代码和注释行 const writeStub = sinon.stub(OrderStreamWriter.prototype, "write"); 我在运行测试时收到相同的错误:

TypeError: Cannot stub non-existent property write

我该如何解决这个问题?

【问题讨论】:

  • 请提供您要测试的TriggerContext类的代码。
  • 您确定您导入到测试文件并调用ObjectStreamWriter 的对象是正确的对象吗?我注意到该类是其文件中的 default 导出。至于带有注释行的测试,您可以将 Writer 的定义更改为 class Writer { write() {} } 并且给定的错误应该消失

标签: javascript mocha.js sinon


【解决方案1】:
// someclass.js

class SomeClass {
  prop1;
  prop2;
  contructor(param1, param2) {
    this.prop1 = param1;
    this.prop2 = param2;
  }

  async someFunction(givenParam) {
    // do something here

    return "somedata";
  }
}

// create a factory . This is what you will use to create an instance rather than using the new word ever time to create a new instance.

const someClassInstanceFactory = (param1, param2) => {
  return new SomeClass(param1, param2);
};

export default { someClassInstanceFactory, SomeClass };

// ********************************************************
// somemodule.js

// this file uses the class we created above as below

import classAndFactory from "./someclass.js";

const moduleFunction = () => {
  const instance = classAndFactory.someClassInstanceFactory(param1, param2);
  // this line returns an instance of SomeClass . it's like calling new SomeClass(pram1, param2);

  const result = instance.someFunction("givenParam");
  console.log(result);

  return result;
  // result should be 'somedata'

  // so how do we unit test moduleFunction and stub instance.someFunction when testing? ?
};

export default moduleFunction;

// *******************************************************************

// somemodule.test.js

import classAndFactory from "./../someclass.js";
import moduleFunction from "./somemodule.js";

const { someClassInstanceFactory, SomeClass } = classAndFactory;

// now if you want to stub any thing what you do is

describe("moduleFunction", () => {
  const fakeSomeClassInstance = new SomeClass(1, 2);

  // arrange

  // stub the factory first to return your fake instance created above.

  const expectedResut = "stubbed yoo";
  sinon
    .stub(classAndFactory, "someClassInstanceFactory")
    .returns(fakeSomeClassInstance);

  someFunctionStub = sinon
    .stub(fakeSomeClassInstance, "someFunction")
    .returns(expectedResut);

  it("must call someFunction function with required argument", () => {
    // act

    const result = moduleFunction();

    // assert
    sinon.assert.calledOnce(someFunctionStub);
    assert.equals(result, expectedResut);
  });
});

【讨论】:

    猜你喜欢
    • 2021-06-10
    • 2015-04-18
    • 1970-01-01
    • 2014-07-17
    • 2014-08-08
    • 2017-07-09
    • 2017-04-27
    • 2016-09-25
    • 2016-01-02
    相关资源
    最近更新 更多