【发布时间】:2018-01-02 17:22:24
【问题描述】:
我正在尝试测试 Angular 4 中组件的 login() 方法,该方法依赖于返回成功或错误的 Observable authService:
被测代码:
login() {
this.loginError = undefined;
this.loadingService.present('Logging In...');
this.authService
.login(this.form.value)
.subscribe(
(currentUser: any) => {
this.loadingService.dismiss();
this.navCtrl
.setRoot('TabsPage')
},
(error: any) => {
this.loadingService.dismiss();
this.loginError = error._body;
console.error('LoginPage :: Login Error:', error);
}
);
}
我知道要成功地对这个方法进行单元测试,我需要隔离它。我为authService 创建了一个存根,并将其注入TestBed:
身份验证存根
export class AuthenticationServiceStub {
login() {};
getCurrentUserFromStorage() {};
logout() {};
};
测试台配置:
TestBed.configureTestingModule({
declarations: [
...components,
],
providers: [
NavController,
LoadingService,
FormBuilder,
{ provide: AuthService, useClass: AuthenticationServiceStub }
],
imports: [
IonicModule.forRoot(LoginPage),
PierDataServicesModule.forRoot(),
],
});
据我了解,要对login() 进行单元测试,我必须测试这四件事:
-
this.loginError设置为未定义 -
this.loadingService.present('Logging In...')被调用 -
this.authService.login(this.form.value)被调用 - 如果
this.authService.login(this.form.value)返回成功,那 成功功能块中的两个方法都被调用,并且如果 错误,错误块中的方法被调用。
这就是我的规范的样子,(我已经成功测试了 1、2、3):
测试:
describe('Login()', () => {
let fixture: ComponentFixture<LoginPage>;
let instance: any = null;
let authService: any;
beforeEach(async(() => TestUtils.beforeEachCompiler([LoginPage]).then(compiled => {
fixture = compiled.fixture;
instance = compiled.instance;
spyOn(instance, 'login').and.callThrough();
spyOn(instance.loadingService, 'present');
spyOn(instance.authService, 'login').and.returnValue({ subscribe: () => {} });
instance.login();
})));
it("should be callable", async(() => {
expect(instance.login).toHaveBeenCalled();
}));
it("should call loadingService.present ", async(() => {
expect(instance.loadingService.present).toHaveBeenCalled();
}));
it("should call authService.login", async() => {
expect(instance.authService.login).toHaveBeenCalled();
});
});
我不知道如何测试 4 号。如何通过成功或错误复制被调用的 Observable,并检查这些函数体中的函数是否运行?
我可以构建模拟 login() 方法并从被测代码中复制功能,但测试模拟方法而不是实际代码似乎真的违反直觉。
我应该使用真正的authService 方法并构建一个模拟后端吗?这是行得通的吗?如果有,怎么做?
我应该使用 Karma 来spyOn 方法并修改它们以执行我想要的操作吗?我想我可以做这样的事情:spyOn(instance.authService, 'login').and.callThrough().and.throwError(),但这种方法没有成功。
【问题讨论】:
-
你能提供一个plunker吗?
标签: angular unit-testing jasmine observable