Reputation: 330
I'm writing unit tests with mocha, chai and sinon in TypeScript. I need to test a class thats constructor expects an object as input parameter, that I want to mock because it is too complex to create. Also some methods of the class use properties of that specific input paramter object. So I also would need to mock methods of that mocked object.
Maybe some code makes it clearer:
My class looks like this (simplified):
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;
}
}
Now I would like to test the getSomething
function. For that I first need to create a Controller object. But the constructor needs a Context object, that I do not have. For that I already tried both of the following:
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();
which both didn't work because property elasticSearch
doesn't exist on type SinonStubbedInstance<Controller>
and I cannot set the elasticSearch property in the first place as it has only a getter.
So now I really don't know what to mock and how to test that getSomething
function. In the best case I want to say that the elasticsearch.search(query)
returns a defined value and this specific value should be handled further in the .then part. I want to skip the elasticSearch access but still want the .then part to be run.
All the documentation about stubs and nested stubs didn't help me.
Upvotes: 0
Views: 554
Reputation: 330
So I managed a working solution. It's probably not best practice but it's the best I could do:
For the Context object I just create an empty Object like that:
contextMock = <Context><unknown>{
clients: {
elasticSearch: new Client()
}
}
then I create with that the controller object:
controller = new Controller(contextMock);
then I can mock the functions of the elasticSearch property like that:
searchStub = sinon.stub(contextMock.clients.elasticSearch, 'search');
And then I have all the things I need to test the class.
Upvotes: 1