在测试Angular服务(具有其自己的依赖项)时,我经常发现自己一直在测试测试套件中的快乐路径和悲伤路径。
我的意思是我有这项服务:
export class MyService {
constructor(private MyClient) {}
public doIt() {
return this.myClient.doTheThing().pipe(
catchError(error => {
// error handling logic
}),
// process the response
)
}
}
现在,我想测试MyService#doIt
成功运行并返回该请求的响应/结果的可观察值,以及MyClient#doTheThing
失败和错误时的测试结果(自从我MyClient#doTheThing
中有一些逻辑要测试)。
测试幸福的道路很容易:
catchError
但是,当// MyClientMock is a mock implementation of MyClient that returns a canned result
// for instance so that I can test against these values when running the tests.
describe(MyService, () => {
let service: MyService
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
MyService,
{ provide: MyClient, useClass: MyClientMock }
],
})
service = TestBed.inject(MyService)
})
it('does the thing', (done) => {
service.doIt().subscribe(result => {
expect(result).toEqual('something')
done()
})
})
})
抛出错误时,如何测试悲伤的路径,并确保MyClient
中的逻辑符合我的预期?
我考虑过创建另一个catchError
并将其命名为MyClientMock
并将其抛出。但是我不能注入它,因为它已经在测试开始时就已经设置好了,并且会干扰其他测试用例。
在这种情况下,有什么好的模式可以用来测试依赖项错误或成功后会发生什么?
答案 0 :(得分:0)
我强烈推荐Jest,胜过业力。
当您需要重新创建模拟函数的复杂行为以使多个函数调用产生不同的结果时,请使用mockImplementationOnce方法:
const myMockFn = jest
.fn()
.mockImplementationOnce(cb => cb(null, true))
.mockImplementationOnce(cb => cb(null, false));
myMockFn((err, val) => console.log(val));
// > true
myMockFn((err, val) => console.log(val));
// > false
这里是模拟的另一个示例,该模拟根据条件参数生成结果:
import { when } from 'jest-when';
const fn = jest.fn();
when(fn).calledWith(1).mockReturnValue('hello world!');
const result = fn(1);
expect(result).toEqual('hello world!');
我想说Jest优于Karma的最大优点是它的非加密,直接的错误消息,使您可以一目了然地确定测试失败的根本原因。