每个测试实例的模拟依赖关系类
问题描述:
我有一个模块实例化导入的类并异步调用这些实例的方法。每个测试实例的模拟依赖关系类
如何在每个测试用例中独立地模拟这些方法,以便这些mock只有在测试用例内部创建的情况下才有意义,因为我无法在测试结束时可靠地恢复mock?
例子:
// 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 */ });
})
})
如果我嘲笑的情形1 B和C同步恢复它们,因为案例2前的C在异步上下文中实例化运行C'S配置将被覆盖。 出于同样的原因,我无法在asserts1之后异步恢复mock。
也有类似的问题:Stubbing a class method with Sinon.js,How to mock dependency classes for unit testing with mocha.js? 但他们没有涵盖异步嘲笑的问题。
答
所以我结束了(不漂亮)构造函数注入。如果你有更好的方法,包括测试和编写异步工厂的完全不同的方法,请分享,我很乐意接受
// tested class
import B_Import from './b';
import C_Import from './c';
let B = B_Import;
let C = C_Import;
export function mock(B_Mock, C_Mock) {
B = B_Mock || B_Import;
C = C_Mock || C_Import;
}
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, { mock as mockB } from './a';
setupMockB = (cfg, mockCallback) => {
const ClassMock = class {
constructor() {
// use cfg
}
doSomething() {}
}
if(mockCallback) {mockCallback(ClassMock.prototype);}
mockB(ClassMock, null)
}
describe('test',() => {
afterEach(() => mockB())
it('case1',() => {
a = new A();
setupMockB(cfg1, (mb) => sinon.stub(mb, 'doSomething').resolves())
return a.someFunction().then(() => { /* asserts1 */ });
})
it('case2',() => {
a = new A();
setupMockB(cfg2, (mb) => sinon.stub(mb, 'doSomething').rejects())
return a.someFunction().then(() => { /* asserts2 */ });
})
})