Reputation: 95
I'm running into problems with typescript during unit testing. I try to unit test an module like the following code example:
import {Express} from 'express'
export interface BootClassInterface {
setup(): Express
}
export class BootClass implements BootClassInterface {
constructor(private express: () => Express ){
}
public test(){
const app = this.express()
app.get("/test", (req, res) => {
res.send("Hello World")
})
return app;
}
}
For testing propose I want to know if express().get() was called and if the first parameter was '/test'. Before I switched to typescript I always used the module sinonJS to spy or stub the functionality so that I could test of a certain dependency was used correctly. Now with Typescript I run into problems with the strict types that I've set in the module. By example:
import * as chai from 'chai'
import 'mocha'
import * as sinon from 'sinon'
import * as express from 'express'
import * as Boot from '../../src/Core/Boot'
const assert = chai.assert
suite('[CORE] unit test /Core/Boot.ts', () => {
let BootClass: Boot.BootClassInterface
setup(() => {
const expressApp = () => {
const app = express()
app.get = sinon.spy()
return app
}
const Services: Boot.BootServicesInterface = { express: expressApp }
BootClass = new Boot.BootClass(Services)
})
test('Do first test', () => {
const app = BootClass.setup()
chai.assert.equal(app.get.called, 1)
})
})
The code example above results in the following Typescript compiling error:
error TS2339: Property 'called' does not exist on type 'ApplicationRequestHandler<Express>'.
I can see why typescript returns this error and somehow it is even obvious. I even know a possible solution where I accept Express as any in the module.
But I'm looking for a more elegant way to be able to spy/stub/mock my dependencies for testing propose, but at the same time have the advantages of strict typing.
Upvotes: 3
Views: 1673
Reputation: 858
AS you have stated you specify Express
as the return type on BootClassInterface
interface. Therefore app
would be considered Express
and it will look up its properties instead of your mock.
You can also just cast one property of app
as any
. Try:
chai.assert.equal((<any>app.get).called, 1)
Or using Sinon type definition:
chai.assert.equal((<SinonSpy>app.get).called, 1)
Upvotes: 2