javascript - Expect jasmine Spy to be called "eventually", before timeout
问题描述
I've written a lot of asynchronous unit tests lately, using a combination of Angular's fakeAsync
, returning Promises from async
test body functions, the Jasmine done
callback, etc. Generally I've been able to make everything work in a totally deterministic way.
A few parts of my code interact in deeply-tangled ways with 3rd party libraries that are very complex and difficult to mock out. I can't figure out a way to hook an event or generate a Promise that's guaranteed to resolve after this library is finished doing background work, so at the moment my test is stuck using setTimeout
:
class MyService {
public async init() {
// Assume library interaction is a lot more complicated to replace with a mock than this would be
this.libraryObject.onError.addEventListener(err => {
this.bannerService.open("Load failed!" + err);
});
// Makes some network calls, etc, that I have no control over
this.libraryObject.loadData();
}
}
it("shows a banner on network error", async done => {
setupLibraryForFailure();
await instance.init();
setTimeout(() => {
expect(banner.open).toHaveBeenCalled();
done();
}, 500); // 500ms is generally enough... on my machine, probably
});
This makes me nervous, especially the magic number in the setTimeout
. It also scales poorly, as I'm sure 500ms is far longer than any of my other tests take to complete.
What I think I'd like to do, is be able to tell Jasmine to poll the banner.open
spy until it's called, or until the test timeout elapses and the test fails. Then, the test should notice as soon as the error handler is triggered and complete. Is there a better approach, or is this a good idea? Is it a built-in pattern somewhere that I'm not seeing?
解决方案
我认为您可以利用callFake
, 基本上在调用此函数后调用另一个函数。
像这样的东西:
it("shows a banner on network error", async done => {
setupLibraryForFailure();
// maybe you have already spied on banner open so you have to assign the previous
// spy to a variable and use that variable for the callFake
spyOn(banner, 'open').and.callFake((arg: string) => {
expect(banner.open).toHaveBeenCalled(); // maybe not needed because we are already doing callFake
done(); // call done to let Jasmine know you're done
});
await instance.init();
});
我们在banner.open 上设置了一个间谍,当它被调用时,它将使用callFake 调用回调函数,我们在这个回调中调用done,让Jasmine 知道我们已经完成了我们的断言。
推荐阅读
- if-statement - Vlookup,Hlookup 在谷歌表格中查找和连接矩阵中的值
- momentjs - date-fns:以给定格式解析日期字符串
- apache-zookeeper - 监控 znode 子节点上的 Zookeeper 添加和删除
- opencv - 在拉普拉斯边缘图像中提取正确的轮廓
- amazon-web-services - 从集成 Step Function (AWS) 获取自定义异常
- c# - 如何将字符串化 json 对象转换为 .net core 2.2 中的模型类?
- html - HTML GET 表单:如何附加到搜索词
- firebase - 使用 firestore 命令获取所有 firestore 安全规则
- batch-file - 自动化默认程序关联
- html - 将徽标与菜单对齐