我有一个角部件,它包含以下部分:
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()的方法,我偶然发现了两篇堆栈溢出文章:模拟测试角5中的FileSaver和你需要间谍来测试是否在茉莉花中调用了一个函数?。基于此,我编写了以下测试:
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();
}));这两个助手方法来自角度测试实例
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);
}
}我的问题是,该测试在以下输出中失败:
错误:预期的间谍拯救已经被调用。 错误:1个定时器仍在队列中。
因此,无论是固执还是断言似乎都不起作用。
如果我从我的click()中删除1 timer(s) still in the queue调用,1 timer(s) still in the queue错误就不再显示了,所以我收集到click()方法可以工作,并触发真正的saveAs()调用--我想用间谍/saveAs()替换这个调用。
我怎么才能解决这个问题?
更新,同时考虑到建议的解决方案:
I.按照my.component.spec.ts的建议,将SiddarthPal中的进口更改为:
import * as FileSaver from 'file-saver';不会有任何区别。测试仍然会导致两个断言错误。
二.按照反光镜的建议,将间谍设置改为:
spyOn(FileSaver, 'saveAs').and.callFake(() => null);也无济于事。测试仍然导致两个断言失败。
我试着写了下面的间谍模拟:
spyOn(FileSaver, 'saveAs').and.callFake(() => {
console.log('--- faking saveAs ---');
return null;
});检查Karma Server输出的输出时,我在任何地方都没有看到这种情况,因此间谍似乎根本没有捕捉到组件对saveAs()的调用。
三.发光机建议取代:
click(page.downloadButton);
advance(fixture);使用
click(page.downloadButton);
flush();确实会使用挂起的计时器错误。然而,这个单极隐藏了一个事实,即使用的是真正的saveAs()调用,而不是间谍/模拟。所以我仍然在寻找办法让它发挥作用。
发布于 2021-03-29 02:44:57
好吧,我现在正努力解决同样的问题。我的间谍也不工作,它调用真正的FileSaver方法。这里的建议也没有为我解决这个问题。
我认为问题是,FileSaver不是一个合适的角度模块的一部分,它只是从FileSaver.js导入的。我在这线程中描述了一个类似的问题。Tl;dr:我解决了这个问题,从Funnel的Funnel用法切换到声明FunnelProvider,并将其注入实际方法的构造器中,如下所示:
constructor(private funnelProvider: FunnelProvider) {}在规范文件中,我能够模拟该提供程序。
所以我想出了两种解决方案:
1.使用 角文件保护程序
我想,好吧,也许有一个FileSaver.js包装库,它为我提供了一个角服务,还有是。但是,依赖项是outdated...that,这可能是一个问题。但是从FileSaver.js切换到角文件保护程序应该是一个简单的改变。
2.为FileSaver.js构建自己的包装器
我现在唯一能想到的其他解决方案是自己将FileSaver的使用包装到它自己的角度模块中。然后导入该模块并将新构建的FileSaverService注入到实际类中。在spec文件中,您可以执行如下操作:
describe("MyComponent", () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let fileSaverServiceSpy: jasmine.SpyObj<FileSaverService>;
beforeEach(() => {
fileSaverServiceSpy= jasmine.createSpyObj('FileSaverService', ['saveAs']);
TestBed
.configureTestingModule({
declarations: [
MyComponent
],
providers: [
{ provide: FileSaverService, useValue: fileSaverServiceSpy }
]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
});
it('saveMyFile() should call FileSaver', () => {
fileSaverServiceSpy.saveAs.and.stub();
MyComponent.saveMyFile("testFileName");
expect(fileSaverServiceSpy.saveAs).toHaveBeenCalled();
});
});然而,所有这些似乎都是为了让间谍工作而做的大量工作。
编辑:我正在测试一个角9项目,这些是我的相关依赖:
"@angular/core": "9.1.12",
"jasmine-core": "3.6.0",
"jasmine-spec-reporter": "6.0.0",
"karma": "5.2.3",
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-firefox-launcher": "^2.0.0",
"karma-jasmine": "4.0.1",
"karma-jasmine-html-reporter": "1.5.4",
"karma-typescript": "5.2.0",https://stackoverflow.com/questions/59281306
复制相似问题