单元测试spyOn angular2中的可观察服务
问题描述:
我有一个服务(ChildService),它依赖于另一个服务(InteractWithServerService)。稍后的服务(InteractWithServerService)用于进行服务器调用并返回“any”类型的可观察值。为了简单起见,我们假设它返回可观察的。我正在尝试为ChildService编写单元测试。单元测试spyOn angular2中的可观察服务
ChildService
@Injectable()
export class ApplicationService {
constructor(private interactWithServerService:InteractWithServerService){;}
public GetMeData():string {
var output:string;
this.interactWithServerService.get("api/getSomeData").
subscribe(response =>{console.log("server response:", response);
output=response});
return output;
}
}
ServerInteractionService
@Injectable()
export class InteractWithServerService {
constructor(private http: Http) {
;
}
get(url: string): Observable<any> {
return this.http.get(this.url);
}
}
测试用例时,我嘲笑依赖服务工作正常。即,不是优选的
class MockInteractWithServerService {
get() {
return Observable.of("some text");
}
}
describe('Service:ChildService',() => {
let childService: ChildService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: InteractWithServerService, useClass: MockInteractWithServerService },
ChildService],
});
beforeEach(inject([ChildService], (actualService: ChildService) => {
childService= actualService;
}));
fit('should call server-call testCall()',() => {
let actualReturnvalue= childService.GetMeData();
expect(actualReturnvalue).toBe("some text");
});
});
上述方法如我可能最终写的“n”的依赖关系的“n” mock类。所以我想用spyOn创建我的单元测试。 但是,测试用例不起作用并抛出“错误:没有提供程序的Http!”。虽然我明白错误是什么,但我想知道为什么它会被抛出,尽管我正在监视依赖服务。看起来像“间谍”不工作。
describe('Service:ChildService',() => {
let childService: ChildService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
InteractWithServerService,
ChildService],
});
spyOn(InteractWithServerService.prototype, 'get').and
.callFake(()=>
{return Observable.of("some text");});
});
beforeEach(inject([ChildService], (actualService: ChildService) => {
childService= actualService;
}));
fit('should call server-call testCall()',() => {
let actualReturnvalue= childService.GetMeData();
expect(actualReturnvalue).toBe("some text");
});
});
我是否缺少明显的东西?
答
However, the test case doesn't work and throws "Error: No provider for Http!".
因为你仍然在providers
服务,所以角试图依然创建
providers: [
InteractWithServerService,
ChildService],
你可以做的,而不是建立一个模拟类是什么,只是像做
providers: [
{
provide: InteractWithServerService,
useValue: { get: Observable.of(..) }
}
]
这是你使用useValue
哪些提供任何对象。这将是注入时使用的值。在上面的例子中,它只是你的模拟方法的一些任意对象。
如果你想窥探,这样就可以提供不同的值,你可以注入InteractWithServerService
,然后做
spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test
你可以做的另一件事是模拟一个虚拟对象
{ provide: Http, useValue: {} }
在HTTP
现在InteractWithServerService
将工作(只需将类添加到像你目前一样的提供者)。你可以偷窥它
let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
谢谢@peeskillet。奇迹般有效。唯一值得关注的是“useValue”,并为您要调用的每个方法返回一个任意对象。它绝对看起来很脏(而不是很干净)。这是角度想要我们写测试的方式吗? –
“任意对象”与使用模拟类没有任何区别。唯一不同的是,它被封装在一个类中。最后,它们都只是任意的对象。你的班级没有扩展实际的服务界面。是什么让这不是任意的?重要的是该对象具有将被调用的方法。 –
我不认为模拟类比useValue更好。我的观点是 - 模拟类和useValue解决方案与旧方法相比只是注入相关类并监视它们,看起来并不干净。 –