我正在尝试测试具有注入服务的组件。我想在测试中提供模拟服务。但是,该测试使用的是原始服务而不是模拟服务(我知道这一点是因为我收到“ HttpClient没有提供者!”错误,并且在测试中输出的原始服务中也有console.log)。
我可以通过导入HttpClientTestingModule来修复错误,但这不能解决使用原始服务而非模拟服务这一事实。
有什么想法我做错了吗?
这是我的测试代码。 Angular版本7
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';
describe('HelloWorldComponent', () => {
let component: HelloWorldComponent;
let fixture: ComponentFixture<HelloWorldComponent>;
let mockHelloWorldService;
beforeEach(() => {
mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
TestBed.configureTestingModule({
imports: [],
declarations: [HelloWorldComponent],
providers: [
[{ provide: HelloWorldService, useClass: mockHelloWorldService }]
]
}).compileComponents();
fixture = TestBed.createComponent(HelloWorldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
更新
我尝试了overrideProvider,现在遇到了“无法读取未定义的属性'subscribe'(未定义)”错误,感觉像是进度...
这是我的测试代码
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';
import { of } from 'rxjs';
describe('HelloWorldComponent', () => {
let component: HelloWorldComponent;
let fixture: ComponentFixture<HelloWorldComponent>;
let mockHelloWorldService;
beforeEach(async(() => {
mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
TestBed.configureTestingModule({
imports: [],
declarations: [HelloWorldComponent]
});
TestBed.overrideProvider(HelloWorldService, { useValue: mockHelloWorldService });
TestBed.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HelloWorldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
这是我的组成部分
import { Component, OnInit } from '@angular/core';
import { HelloWorldService } from '../../services/hello-world.service';
@Component({
selector: 'app-hello-world',
templateUrl: './hello-world.component.html',
providers: [HelloWorldService]
})
export class HelloWorldComponent implements OnInit {
helloWorldMessage: any;
constructor(private helloWorldService: HelloWorldService) { }
ngOnInit() {
this.getHelloWorldMsg();
}
getHelloWorldMsg() {
this.helloWorldService
.getHelloWorld()
.subscribe((data) => {
this.helloWorldMessage = data;
}, err => this.handleErrorResponse('There was a problem loading the hello world message', err));
}
handleErrorResponse(errorMsg: string, error?: any) {
console.log("There was a problem getting the message");
}
}
这是我的服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
@Injectable()
export class HelloWorldService {
constructor(private http: HttpClient) { }
getHelloWorld(): Observable<any> {
console.log("Why is the test coming here when I provide a mock?");
var getHelloWorldApiUrl = environment.apiUrl + "/api/v1.0/helloworld/GetHelloWorldMessageAuth";
return this.http
.get(getHelloWorldApiUrl);
}
}
答案 0 :(得分:1)
也许您的HelloWorldService是在组件提供程序中声明的。因此,您需要使用https://angular.io/api/core/testing/TestBed#overrideComponent来替换提供程序。
答案 1 :(得分:1)
我在上面的代码中看到两个问题:
HelloWorldService
时,您已指定useClass
,但提供了一个对象(jasmine.createSpyObj()
产生的对象),因此应改为指定{{1 }}。我希望这会有所帮助。
好的,您已经走了很长一段路!您纠正了我上面概述的两个问题,按照我在对另一个答案的评论中的建议,在useValue
之前完成了overrideProvider()
并将compileComponents()
包裹在beforeEach()
内
我要求查看所有其他代码的原因是,我可以将其快速放入以下StackBlitz中进行测试。正如您在该StackBlitz中看到的那样,该测试现在通过了。
我只在async()
中添加了一行以从您的间谍中声明returnValue,以便您组件中的订阅具有一个Observable来订阅:
beforeEach()
我在调用mockHelloWorldService.getHelloWorld.and.returnValue(of('Test Message'));
之前添加了此内容,因为它将调用fixture.detectChanges()
,并且间谍需要在执行ngOnInit()
之前设置返回值,这样它才能正确执行而不会给您您看到的错误。
我还在规范中添加了一行,以展示如何测试Observable的结果是否正确设置为组件变量:
ngOnInit()
请注意,通过在组件声明的providers数组中指定HelloWorldService,将使测试变得非常复杂。相反,如果您以root身份作为单例提供此服务,则可以简化很多事情,包括如何进行测试。在Official Docs中查看详细信息。