您的测试失败的原因是您的组件中的 ngOnInit() 正在进行实际的 http 调用以获取该资源 dummy.json。
良好的单元测试实践通常表明您应该模拟应用程序的大部分部分,被测单元除外。这为您提供了更多控制权,并允许您的测试更好地解释发生故障时的错误所在。当我们对该资源使用实际的 http 调用并且测试失败时,我们不知道是因为未检索到资源还是因为标题未在 h1 标记中呈现。这两个问题彼此无关,应该在单独的测试用例中。为此,我们模拟了 http 调用,因此我们可以确保收到成功的响应,然后只关注标题。
为此,我们可以使用HttpClientTestingModule。
这是app.component.ts 的示例,以反映您上面的示例:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
template: `
<h1>{{ title }} app is running!</h1>
`
})
export class AppComponent implements OnInit {
favorites: {};
title = 'Demo';
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get('../assets/data/dummy.json').subscribe(result => {
this.favorites = result;
});
}
}
为了让您的AppComponent should render title in a h1 tag 测试通过,这是您的规范文件app.component.spec.ts:
import { TestBed, async } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
imports: [ HttpClientTestingModule ]
}).compileComponents();
}));
it('AppComponent should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Demo app is running!');
});
});
注意,我们所做的就是将HttpClientTestingModule 添加到TestBed.configureTestingModule({}) 的导入列表中。我们不需要做任何其他事情,当在此TestBed 中创建组件并请求HttpClient 时,TestBed 将为它提供来自HttpClientTestingModule 的HttpClient。这将阻止您的所有请求实际发送,现在您的测试将通过。
这适用于您的情况,但现在它也允许您开始对 http 请求和响应执行测试。查看https://angular.io/guide/http#testing-http-requests 了解更多关于HttpClientTestingModule 和一般http 测试的信息。