I'm trying to unit test the following controller:
export class MyController extends BaseController {
constructor() {
super();
this.repository = new MyRepository();
}
public getData(req: Request, res: Response, next: NextFunction) {
this.repository.getData(req.params.param1).then((result) => {
return this.ok(req, res, result.resources) // calls ok() method from base controller
}, (err: Error) => {
next(err)
});
}
}
I would like to stub the MyRepository.getData
which returns a Promise<MyResult>
I also want to stub the BaseController.ok
method to ensure it's called with the data returned from repo.
Here is my test:
it("should call the repository", (done) => {
var mockReq = httpMocks.createRequest();
var mockResp = httpMocks.createResponse();
const mockNext: NextFunction = stub();
mockReq.params.param1 = "value1";
let sampleResult = new MyResult();
const getDataStub = stub(MyRepository.prototype, "getData").resolves(sampleResult);
const okStub = stub(MyController.prototype, "ok");
new MyController().getData(mockReq, mockResp, mockNext);
expect(getDataStub).to.have.been.calledWith("value1"); // passes ok
expect(okStub).to.have.been.called; // fails
done()
});
The test fails when checking, if the okStub
has been called at least once. If I debug the code I can see that the BaseController.ok
is actually called, but after the evaluation in test.
Looks like code inside of getData.then
gone to another cycle at event loop.
Try to place done() inside of this.ok
like this
stub(MyController.prototype, "ok").callsFake(() => {
done();
});