I have a module which instantiates imported classes and asynchronously calls methods of those instances.
How can I mock those methods independently per test case so these mocks only make sense for instance, which is created inside a test case, given that I cannot reliably restore mocks at the end of the test?
Example:
// tested class
import B from './b';
import C from './c';
export default class A {
someFunction() {
let instanceB = new B();
return instanceB.doSomething()
.then(() => this.doSomethingElse())
.then((data) => {
// async context, other tests will start before this.
let instanceC = new C(data);
});
}
}
// test
import A from './a';
describe('test', () => {
it('case1', () => {
a = new A();
// Mock B, C with config1
return a.someFunction().then(() => {/* asserts1 */ });
})
it('case2', () => {
a = new A();
// Mock B, C with config2
return a.someFunction().then(() => {/* asserts2 */ });
})
})
If I mock B and C in case1 and restore them synchronously, C's config will be overwritten because case2 runs before C's instantiation in the async context. For the same reason I cannot restore mocks asynchronously after asserts1.
There are similar questions: Stubbing a class method with Sinon.js, How to mock dependency classes for unit testing with mocha.js? but they don't cover the problem of async mocks.