使用 Sinon 存根创建对象作为构造函数的输入
Create Object with Sinon stub as input to constructor
我正在用 TypeScript 中的 mocha、chai 和 sinon 编写单元测试。我需要测试一个 class 构造函数需要一个对象作为输入参数,我想模拟它,因为它太复杂而无法创建。 class 的一些方法也使用该特定输入参数对象的属性。所以我还需要模拟那个模拟对象的方法。
也许一些代码更清楚:
我的 class 看起来像这样(简化):
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 属性 因为它只有一个 getter.
所以现在我真的不知道要模拟什么以及如何测试 getSomething
函数。在最好的情况下,我想说 elasticsearch.search(query)
returns 一个定义的值,这个特定的值应该在 .then 部分进一步处理。我想跳过 elasticSearch 访问,但仍然希望 .then 部分为 运行.
所有关于存根和嵌套存根的文档都没有帮助我。
所以我管理了一个可行的解决方案。这可能不是最佳做法,但这是我能做的最好的做法:
对于 Context 对象,我只是像这样创建一个空对象:
contextMock = <Context><unknown>{
clients: {
elasticSearch: new Client()
}
}
然后我用它创建控制器对象:
controller = new Controller(contextMock);
然后我可以像这样模拟 elasticSearch 属性 的功能:
searchStub = sinon.stub(contextMock.clients.elasticSearch, 'search');
然后我就拥有了测试 class 所需的所有东西。
我正在用 TypeScript 中的 mocha、chai 和 sinon 编写单元测试。我需要测试一个 class 构造函数需要一个对象作为输入参数,我想模拟它,因为它太复杂而无法创建。 class 的一些方法也使用该特定输入参数对象的属性。所以我还需要模拟那个模拟对象的方法。
也许一些代码更清楚:
我的 class 看起来像这样(简化):
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 属性 因为它只有一个 getter.
所以现在我真的不知道要模拟什么以及如何测试 getSomething
函数。在最好的情况下,我想说 elasticsearch.search(query)
returns 一个定义的值,这个特定的值应该在 .then 部分进一步处理。我想跳过 elasticSearch 访问,但仍然希望 .then 部分为 运行.
所有关于存根和嵌套存根的文档都没有帮助我。
所以我管理了一个可行的解决方案。这可能不是最佳做法,但这是我能做的最好的做法:
对于 Context 对象,我只是像这样创建一个空对象:
contextMock = <Context><unknown>{
clients: {
elasticSearch: new Client()
}
}
然后我用它创建控制器对象:
controller = new Controller(contextMock);
然后我可以像这样模拟 elasticSearch 属性 的功能:
searchStub = sinon.stub(contextMock.clients.elasticSearch, 'search');
然后我就拥有了测试 class 所需的所有东西。