Jasmine 测试符合可观察角度2的方法
我想在Angular 2组件中测试一个方法,该组件订阅了从服务中的方法返回的可观察对象。以下是服务方法的代码摘要:Jasmine 测试符合可观察角度2的方法,jasmine,angular,rxjs,Jasmine,Angular,Rxjs,我想在Angular 2组件中测试一个方法,该组件订阅了从服务中的方法返回的可观察对象。以下是服务方法的代码摘要: public create(user: User): Observable<any> { return this.http.post(this._api.create, JSON.stringify(user), { headers: this.apiConfig.getApiHeaders() }).map((res: Response
public create(user: User): Observable<any> {
return this.http.post(this._api.create,
JSON.stringify(user), {
headers: this.apiConfig.getApiHeaders()
}).map((res: Response) => res.json());
}
这是到目前为止我的规范,但当我尝试窥视localStorage.setItem时,它返回为未被调用。我的理解是,它可能正在检查它是否在实际被调用之前被调用过
it('Should login a user and on success store a token in localStorage',
injectAsync([TestComponentBuilder], (tcb) => {
return tcb.createAsync(Login).then((fixture) => {
let instance = fixture.debugElement.componentInstance;
localStorage.clear();
spyOn(localStorage, 'setItem');
instance.onSubmit({userId: 'some@email.com', password: 'password', siteName: 'sample'});
expect(localStorage.setItem).toHaveBeenCalled();
});
})
);
我想知道是否需要模拟this.\u authentication.create方法来返回一个新的可观察对象,其中包含模拟响应
经过更多的研究,有几篇文章指出我确实需要模拟服务并返回一个同步运行的Observable.of()来解决这个问题,我将复制下面的代码。然而,这仍然不起作用,我已经工作了一天的大部分时间,我觉得这不应该是那么难,任何帮助感谢
class MockAuthentication extends Authentication {
public create(user: Object): Observable<any> {
return Observable.of({'test': 'test'});
}
}
class-MockAuthentication扩展了身份验证{
公共创建(用户:对象):可观察{
返回({'test':'test'})的可观测值;
}
}
我想你应该在你的组件中注入一个mock路由器
实例,然后在mock路由器上调用导航(['/Home'])
后,你检查是否调用了本地存储。setItem(…)
。好吧,我花了一天的大部分时间,但我终于破解了它。与使用injectAsync和TestComponentBuilder来设置规范不同,我只需要使用inject并将组件注入,就像您使用服务一样。这似乎很好,因为我不需要在视图中测试任何事件
以下是最终的规范:
it('Should set token in localStorage, set the new user,
and navigate to home page on succesful login',
inject([Login], (login) => {
login.router.config([ { path: '/', name: 'Home', component: Home }]);
spyOn(localStorage, 'setItem');
spyOn(login._currentUser, 'set');
spyOn(login.router, 'navigate');
login.onSubmit({ userId: 'some@email.com', password: 'password', siteName: 'sample' });
expect(localStorage.setItem).toHaveBeenCalledWith('token', 'newToken');
expect(login._currentUser.set).toHaveBeenCalledWith({ 'test': 'one' });
expect(login.router.navigate).toHaveBeenCalledWith(['/Home']);
}));
希望这能对将来的人有所帮助
基本上你可以在这里做几件事。首先,用您想要的令牌(或其他响应)的简单可观察响应来存根您的http调用(我猜是从服务中)
service.stub.ts
export class MyStub {
public create(user: User): Observable<User> {
return Observable.of('insert test token here');
}
// other stubbed methods ...
}
导出类MyStub{
公共创建(用户:用户):可观察{
返回可观察的('在此处插入测试标记');
}
//其他存根方法。。。
}
然后在测试中:
mycop.spec.ts
let comp: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let sst: ServiceStub;
describe('MyComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(OnboardFacilityNewComponent, {
set: {
providers: [
{ provide: MyService, useClass: ServiceStub },
]
}
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(MyComponent);
comp = fixture.componentInstance;
st = fixture.debugElement.injector.get(MyService);
});
}));
it('should submit new onboardFacility', fakeAsync(() => {
const sst = spyOn(sst, 'create').and.returnValue(
Observable.of('some token here')
);
comp.onSubmit(testUser);
fixture.detectChanges();
expect(comp.token).toEqual('some token here');
expect(spy.calls.any()).toEqual(true);
}));
});
let comp:MyComponent;
let夹具:组件夹具;
让sst:ServiceStub;
描述('MyComponent',()=>{
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[MyComponent],
架构:[无错误\u架构]
}).覆盖组件(车载设备NewComponent{
设置:{
供应商:[
{provide:MyService,useClass:ServiceStub},
]
}
})
.compileComponents()
.然后(()=>{
fixture=TestBed.createComponent(MyComponent);
comp=夹具。组件状态;
st=fixture.debugElement.injector.get(MyService);
});
}));
它('应提交新的车载设备',fakeAsync(()=>{
const sst=spyOn(sst,'create')。和.returnValue(
可观察的('此处的某个标记')
);
提交公司(测试用户);
fixture.detectChanges();
expect(comp.token).toEqual(这里是一些token);
expect(spy.calls.any()).toEqual(true);
}));
});
在这里,您可以简单地用测试数据替换实际数据来测试测试的行为,而不是测试床、服务、本地存储等。显然,我在这里编写的测试假设您将从服务返回的令牌存储在组件中,而不是本地存储中,但我只是简单地展示概念,而不是您的特定用例
在您的用例中,您还需要在路由器上设置存根,您可以学习如何执行由于订阅,在它们被调用之前,感觉会进行检查,但我对可观察对象不熟悉。此外,我们过去在Angular 1中只使用spyOn(localStorage,'setItem'),但我很难弄清楚如何在Angular 2中使用spyOn。我的缺点是,看起来您仍然使用spyOn,我的问题是我无法弄清楚您需要从何处导入“spyOn”,但似乎您已经拥有了它。但我关于之前发生的支票的陈述似乎仍然成立。我已经更新了我的问题以包含规范。这毫无意义。。你为什么在模拟服务中呼叫spyOn?如果它是模拟的,它也返回一个模拟值,您不需要使用returnValue Jasmine函数返回另一个模拟值。@EliasGarcia,因为您正在确定函数逻辑是否调用依赖项。间谍是可选的。
let comp: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let sst: ServiceStub;
describe('MyComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(OnboardFacilityNewComponent, {
set: {
providers: [
{ provide: MyService, useClass: ServiceStub },
]
}
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(MyComponent);
comp = fixture.componentInstance;
st = fixture.debugElement.injector.get(MyService);
});
}));
it('should submit new onboardFacility', fakeAsync(() => {
const sst = spyOn(sst, 'create').and.returnValue(
Observable.of('some token here')
);
comp.onSubmit(testUser);
fixture.detectChanges();
expect(comp.token).toEqual('some token here');
expect(spy.calls.any()).toEqual(true);
}));
});