在Jasmine中使用Subject和localstorage测试Angular服务



我有一个需要测试的登录页面,它使用了一个身份验证服务。粗略地说,当按下登录按钮时,在某个时刻会发生以下情况:

this.userService.$authentification.subscribe((res)=>{
if(res.success){
this.router.navigate(['/dashboard']);
}else{
console.error(res.error.code)
this.error=res.error;
}
})
this.userService.authentification(login, pwd);

(这是我应该测试的代码的一部分,因此我不应该修改它)

内部,$ authentication是一个Subject:

$authentification = new Subject<any>();

,附加到服务方法认证:

authentification(login : string, password : string){
let body = {
login: login,
password: password
}
this.jwtLocalstorage.remove();
let post = this.http.post<any>(environment.api + 'user/login/index.php', body, {}).subscribe(response => {
post.unsubscribe();
if(response.jwt){
this.jwtLocalstorage.add(response.jwt, response.data.id);
this.$authentification.next({
success:true,
error: null
});
}else{
this.$authentification.next({
success:false,
error: {code:"0X"}
});
}
},response => {
post.unsubscribe();
this.$authentification.next({
success:false,
error: response.error
});
});
}

服务调用身份验证API,将结果存储在本地存储中,然后在Subject对象中提供确认,然后登录页面将使用该确认来决定下一步要做什么。

在测试登录页面时,我应该在这里模拟什么?我应该模拟服务、主题和本地存储,还是从组件获取服务,然后模拟主题和本地存储?我不太确定该怎么做。

单元测试是关于测试一个代码单元。该单元之外的所有内容都应该被模拟.

所以是的,你应该嘲笑你的服务。从这里开始,考虑一下:既然你已经嘲笑了这个服务,为什么还要嘲笑它中的其他东西呢?mock没有依赖关系,所以只模拟服务,不模拟其他任何东西。

下面是可以用来测试代码的最简单的模拟


const state = new Subject<any>();
serviceMock: any = {
$authentification: state.asObservable(),
authentification: jasmine.createSpy()
};
从那里,只需将这个mock注入到组件 中

component = new MyComponent(serviceMock);

现在,做一个有意义的测试


it('Should redirect in case of success', (done) => {
state.pipe(first()).subscribe(() => {
expect(component.router.navigate)
.toHaveBeenCalledOnceWith(['/dashboard']);
done();
});
component.yourFunctionToCallToTest();
state.next({ success: true });
});

最新更新