Angular 7:在UnitTest中模拟FileSaver.saveAs

问题描述 投票:0回答:1

我有一个包含以下部分的角度分量:

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 5Do 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()调用而不是间谍/模拟的事实。所以我仍在寻找使它起作用的方法。

angular karma-jasmine
1个回答
0
投票

尝试如下重写beforeEach

beforeEach(() => {
    spyOn(FileSaver, 'saveAs').and.callFake(() => null);
});
© www.soinside.com 2019 - 2024. All rights reserved.