我一直在尝试模拟通过构造函数传入的类,到目前为止,我所遇到的所有示例都已初始化构造函数内部的依赖项。
据我了解,玩笑用其重写的构造函数替换了这些依赖关系,但是由于我自己传递了依赖关系,因此在初始化UnderTest
时需要一个可传递的实例。
对于理想的情况,我理想地是寻找一种类似于Mockito的行为。
const mockedDependency = ???
const underTest = new UnderTest(mockedDependency)
...
Proceed to write tests for underTest
这是我要测试的代码。请假设MockedDependency
拥有自己的依赖项,并且也要传递给构造函数。
export default class UnderTest {
private mockedDependency : MockedDependency
constructor(mockedDependency: MockedDependency) {
this.mockedDependency = mockedDependency
}
public methodUnderTest(parameter: string) {
const mockedResult = this.mockedDependency.returnSomething(parameter)
return this.doSomethingElse(mockedResult)
}
public methodUnderTest2(parameter1: string, parameter2: string) {
const mockedResult = this.mockedDependency.returnSomething2(parameter1, parameter2)
return this.doSomethingElse(mockedResult)
}
private doSomethingElse(mockedResult: string) {
return mockedResult
}
}
您将如何进行单元测试UnderTest
类?
奖励点是一种在每次测试中或通过输入设置mockedDependency
方法结果的方法。
编辑: 对于那些偶然遇到相同问题的人,可能的解决方案:
可以将变量强制转换为所需对象,并像这样重写方法:
const mockedDependency = {
returnSomething(parameter: string) {
return parameter
}
} as MockedDependency
const underTest = new UnderTest(mockedDependency)
它远非完美,但适用于更简单的情况。
谢谢!
答案 0 :(得分:0)
这是解决方案:
UnderTest.ts
:
export interface MockedDependency {
returnSomething(...args: any[]): any;
returnSomething2(...args: any[]): any;
}
export default class UnderTest {
private mockedDependency: MockedDependency;
constructor(mockedDependency: MockedDependency) {
this.mockedDependency = mockedDependency;
}
public methodUnderTest(parameter: string) {
const mockedResult = this.mockedDependency.returnSomething(parameter);
return this.doSomethingElse(mockedResult);
}
public methodUnderTest2(parameter1: string, parameter2: string) {
const mockedResult = this.mockedDependency.returnSomething2(parameter1, parameter2);
return this.doSomethingElse(mockedResult);
}
private doSomethingElse(mockedResult: string) {
return mockedResult;
}
}
UnderTest.spec.ts
:
import UnderTest, { MockedDependency } from './UnderTest';
const mockedDeps: jest.Mocked<MockedDependency> = {
returnSomething: jest.fn(),
returnSomething2: jest.fn()
};
const underTest = new UnderTest(mockedDeps);
describe('UnderTest', () => {
afterEach(() => {
jest.resetAllMocks();
});
describe('#methodUnderTest', () => {
it('should correctly', () => {
mockedDeps.returnSomething.mockReturnValueOnce('mocked result');
const actualValue = underTest.methodUnderTest('1');
expect(actualValue).toBe('mocked result');
expect(mockedDeps.returnSomething).toBeCalledWith('1');
});
});
describe('#methodUnderTest2', () => {
it('should correctly', () => {
mockedDeps.returnSomething2.mockReturnValueOnce('mocked result');
const actualValue = underTest.methodUnderTest2('2', '3');
expect(actualValue).toBe('mocked result');
expect(mockedDeps.returnSomething2).toBeCalledWith('2', '3');
});
});
});
具有100%覆盖率报告的单元测试结果:
PASS src/stackoverflow/55966013/UnderTest.spec.ts
UnderTest
#methodUnderTest
✓ should correctly (5ms)
#methodUnderTest2
✓ should correctly (1ms)
--------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
UnderTest.ts | 100 | 100 | 100 | 100 | |
--------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.597s, estimated 8s
以下是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55966013