我有一个包含以下部分的角度分量:
my.component.html(摘录)
<button pButton
class="download ui-button ui-button-secondary"
(click)="exportFile(logEvent)"
icon="fas fa-file-download">
</button>
my.component.ts(摘录)
import {saveAs} from 'file-saver';
exportFile(logEvent: LogEvent) {
saveAs(new Blob([logEvent.details]), 'log-details.txt');
}
这在我的应用程序中非常有效。我现在想在单元测试中对此进行测试。在寻找一种确保已调用saveAs()的方法时,我偶然发现了两篇stackoverflow文章:mocking - Testing FileSaver in Angular 5和Do you need spies to test if a function has been called in Jasmine?。基于此,我编写了以下测试:
my.component.spec.ts(摘录)
import * as FileSaver from 'file-saver';
beforeEach(() => {
spyOn(FileSaver, 'saveAs').and.stub();
});
it('should download a file if the download button is clicked', (fakeAsync() => {
// fakeAsync because in my real test, there are httpClient test aspects as well
advance(fixture);
expect(page.downloadButton).toBeDefined();
click(page.downloadButton);
advance(fixture);
expect(FileSaver.saveAs).toHaveBeenCalled();
}));
这两个辅助方法来自Angular Testing Example:
export function advance(f: ComponentFixture<any>): void {
tick();
f.detectChanges();
}
export const ButtonClickEvents = {
left: {button: 0},
right: {button: 2}
};
export function click(el: DebugElement | HTMLElement, eventObj: any = ButtonClickEvents.left): void {
if (el instanceof HTMLElement) {
el.click();
} else {
el.triggerEventHandler('click', eventObj);
}
}
我的问题是,该测试失败,并显示以下输出:
错误:预期的间谍saveA已被调用。
错误:队列中还有1个计时器。
所以看来,存根或断言似乎都不起作用。
[如果我从测试中删除click()
调用,则不再显示1 timer(s) still in the queue
错误,因此我认为click()方法有效并触发了真正的saveAs()
调用-我想用间谍/模拟。
我该如何解决?
更新,考虑了建议的解决方案:
I。根据SiddarthPal的建议,将my.component.spec.ts中的导入更改为:
import * as FileSaver from 'file-saver';
没有任何区别。测试仍然会导致两个断言错误。
II。根据uminder的建议将间谍设置更改为:
spyOn(FileSaver, 'saveAs').and.callFake(() => null);
也不起作用。测试仍然导致两个失败的断言。
我尝试如下编写间谍程序:
spyOn(FileSaver, 'saveAs').and.callFake(() => {
console.log('--- faking saveAs ---');
return null;
});
检查Karma Server输出的输出,我什么地方都看不到,所以看起来间谍根本无法捕获组件对saveAs()的调用。
III。 uminder建议替换:
click(page.downloadButton);
advance(fixture);
with
click(page.downloadButton);
flush();
会消耗挂起的计时器错误。但是,该onyl隐藏了使用真正的saveAs()
调用而不是间谍/模拟的事实。所以我仍在寻找使它起作用的方法。
尝试如下重写beforeEach
:
beforeEach(() => {
spyOn(FileSaver, 'saveAs').and.callFake(() => null);
});