首页 > 解决方案 > 使用 Sinon 存根创建对象作为构造函数的输入

问题描述

我正在 TypeScript 中使用 mocha、chai 和 sinon 编写单元测试。我需要测试一个构造函数需要一个对象作为输入参数的类,我想模拟它,因为它太复杂而无法创建。此外,该类的某些方法使用该特定输入参数对象的属性。所以我还需要模拟该模拟对象的方法。

也许一些代码使它更清楚:

我的班级看起来像这样(简化):

class Controller {
   constructor(context: Context) {
        this._context = context;
   }
   protected get elasticSearch(): Client {
         return this._context.clients.elasticSearch;
   }

   // the next method should be tested
   public async getSomething(input1: string, input2: string): Promise<ResultObject> {
       const result = new ResultObject();
       await this.elasticSearch.search(query).then((_res)=>{
           // do something with _res
           result.prop = _res;
       });
       return result;
   }
}

现在我想测试这个getSomething功能。为此,我首先需要创建一个 Controller 对象。但是构造函数需要一个我没有的 Context 对象。为此,我已经尝试了以下两种方法:

const controllerStub = sinon.createStubInstance(Controller);
controllerStub.elasticSearch = sinon.stub();
--------------------------------------------------
const contextMock = <Context>{};
const controller = new Controller(contextMock);
controller.elasticSearch = sinon.stub();
controller.elasticSearch.search = sinon.stub();

两者都不起作用,因为elasticSearch类型上不存在属性,SinonStubbedInstance<Controller>并且我无法首先设置 elasticSearch 属性,因为它只有一个吸气剂。

所以现在我真的不知道要模拟什么以及如何测试该getSomething功能。在最好的情况下,我想说elasticsearch.search(query)返回一个定义的值,这个特定的值应该在 .then 部分进一步处理。我想跳过 elasticSearch 访问,但仍希望运行 .then 部分。

所有关于存根和嵌套存根的文档都没有帮助我。

标签: typescriptunit-testingmocha.jschaisinon

解决方案


所以我管理了一个可行的解决方案。这可能不是最佳实践,但这是我能做的最好的:

对于 Context 对象,我只创建一个像这样的空对象:

contextMock = <Context><unknown>{
                  clients: {
                      elasticSearch: new Client()
                  }
               }

然后我用那个控制器对象创建:

controller = new Controller(contextMock);

然后我可以像这样模拟 elasticSearch 属性的功能:

searchStub = sinon.stub(contextMock.clients.elasticSearch, 'search');

然后我拥有了测试课程所需的所有东西。


推荐阅读