Let say I have an Express route which is handled by a controller. The controller uses a service and the service uses a repository to talk to a data source.
I want to create an integration test using Supertest to test that route :
test -> my Express app -> controller -> service -> repository -> data source
My problem is that I need to mock the repository/data source, to run the test! I want to hardcode some values as if they were coming from the real data source. What are my options?
In a Java world, I would be using dependency injection with Spring or Guice and I would replace the repository with a mock version that way. What are the patterns to achieve such mocking in a Typescript/Node.js world?
I guess using plain Javascript I could use Proxyquire
and its Globally override require feature, to mock the repository from the test itself. But I'm not sure this works well with Typescript.
So what are the recommended ways of mocking a "deep" component (a transitive dependency) from within a test file, using Typescript and Node.js?
Modules are cached after the first time they are loaded, so you can just load them first in your test file and stub them using a library like sinon.
Consider the following code:
// dependency.ts
export function foo(){
return 'foo';
}
// app.ts
import {foo} from './dependency';
export default function main(){
return 'winner ' + foo();
}
You could test app.ts stubbing its dependency with sinon in the following way:
import * as Dependency from '../src/dependency';
import main from '../src/app';
describe('test dependency', () => {
var fooStub;
beforeEach(() => {
fooStub = sinon.stub(Dependency, 'foo');
fooStub.returns('la la lang');
});
afterEach(()=>{
fooStub.restore();
})
it('uses stubbed dependency', ()=>{
expect(main()).to.be.equal('winner la la lang');
});
it('can return different values on other tests', ()=>{
fooStub.returns('moonlight');
expect(main()).to.be.equal('winner moonlight');
});
});
So basically for your integration tests you can import and stub your dependencies before starting the app. I have done this creating an app.proxy.ts
file:
app.proxy
import your repository and stub it to return the predefined data. After setting up the stub, import the real app.ts
and export it.app.proxy
instead of app and use it with supertest. This will give you the app in the end, but after setting up the stubbed dependency!If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With