这样考虑两个类A
和B
:
class A {
private b: B;
public constructor(b: B){
this.b=b;
}
public doSomething(){
this.b.myMethod();
}
}
class B {
public myMethod(){...}
public someOtherMethod(){...}
}
我想在模拟A
的行为的同时测试类B.myMethod()
目前,我们这样做是这样的:
const bMock: Partial<B> = {
myMethod: jest.fn(<some mock here>),
}
const sut = new A(bMock as any);
sut.doSomething();
expect(bMock.myMethod).toBeCalled();
我们想要实现的结果是相似的,但是不必通过as any
传递模拟,也不必自己模拟所有方法。选中模拟类型对我们非常重要,因为否则我们将无法通过此测试捕获模拟依赖项中的重大更改。
我们也已经研究过sinon
,但是在某些情况下,我们不希望调用模拟依赖项的构造函数,因此在创建后对对象进行存根处理是不可行的。对整个类进行存根会导致类似上述的问题。
答案 0 :(得分:0)
如何创建泛型? (您可以使用示例中的Partial,但是在调用它之前必须检查是否提供了'sut.doSomething'实现。
class B {
public myMethod(){}
public someOtherMethod(){}
}
class A<T extends B> {
private b: T;
public constructor(b: T){
this.b=b;
}
public doSomething(){
this.b.myMethod();
}
}
const bMock = {myMethod: jest.fn(), someOtherMethod: jest.fn()}
const sut = new A(bMock)
sut.doSomething()
expect(bMock.myMethod).toBeCalled();
答案 1 :(得分:0)
我通过使用Substitute找到了一个不错的解决方案。
唯一的问题是自述文件中提到的缺少null / undefined的检查。仍然比使用as any
更好。
import Substitute, { SubstituteOf } from '@fluffy-spoon/substitute';
class A {
private b: B;
public constructor(b: B) {
this.b = b;
}
public doSomething() {
return this.b.myMethod();
}
}
class B {
public myMethod() {
return 'realMethod';
}
public someOtherMethod() {
return 'realSomeOtherMethod';
}
}
let bMock: SubstituteOf<B>;
beforeEach(() => {
bMock = Substitute.for<B>();
});
test('empty mock', () => {
const sut = new A(bMock);
console.log(sut.doSomething()); // Output: '[Function]'
});
test('mock myMethod', () => {
bMock.myMethod().returns('You got mocked!');
const sut = new A(bMock);
console.log(sut.doSomething()); // Output: 'You got mocked!'
});
test('does not compile', () => {
bMock.myMethod().returns(1337); // Will show compilation error due to incompatible type (string vs. number)
const sut = new A(bMock);
console.log(sut.doSomething());
});
test('missing null checks', () => {
bMock.myMethod().returns(); // Will not complain
const sut = new A(bMock);
console.log(sut.doSomething()); // Output 'undefined'
});