我有以下组件:
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, FormControl, Validators} from "@angular/forms";
import {ValidationService} from "../../services/validation.service";
import {Router} from "@angular/router";
import {UsersService} from "../../services/users.service";
import {MdlSnackbarService} from "angular2-mdl";
@Component({
selector: 'app-signup',
templateUrl: 'signup.component.html',
styleUrls: ['signup.component.css'],
providers: [UsersService]
})
export class SignupComponent implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder,
private router: Router,
private usersService: UsersService,
private mdlSnackbarService: MdlSnackbarService) {
this.form = fb.group({
"email": new FormControl("", [Validators.required, ValidationService.emailValidator]),
"password": new FormControl("", Validators.required)
});
}
ngOnInit() {
}
onSignup() {
if (this.form.valid) {
let email = this.form.value.email;
let password = this.form.value.password;
this.usersService.signup(email, password)
.then(() => {
this.router.navigate(['/app/home']);
})
.catch(err => {
this.mdlSnackbarService.showToast(err);
});
}
}
}
我正在尝试为此设置一些单元测试,但经过几个小时后,我仍然无法运行最简单的测试(由角度CLI自动生成的测试):
fdescribe('SignupComponent', () => {
let component: SignupComponent;
let fixture: ComponentFixture<SignupComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SignupComponent ],
providers: [UsersService, AngularFire, MdlDialogOutletService],
imports: [
AngularFireModule.initializeApp(firebaseConfig),
ReactiveFormsModule,
CommonModule,
RouterTestingModule.withRoutes([
// { path: 'settings/:collection/edit/:item', component: DummyComponent }
])
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SignupComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
我收到以下错误:No provider for MdlSnackbarService!
所以我所做的是将MdlSnackbarService
添加到提供商configureTestingModule
:
providers: [UsersService, AngularFire, MdlDialogOutletService, MdlSnackbarService]
但是,我得到的错误是Error: No component factory found for MdlSnackbarComponent. Did you add it to @NgModule.entryComponents?
我不知道如何修复。我没有找到任何与单元测试有关的答案。
有谁知道如何解决这个问题?
答案 0 :(得分:1)
您应该对所有这些服务使用模拟,即Router
,UserService
和MdlSnackbarService
。您希望能够控制这些服务在测试期间执行的操作。你真的不关心服务本身的作用。重要的是组件如何与它们交互。这是你想要测试的。
要设置模拟,您可以执行类似
的操作let router;
let userService;
let snackbar;
beforeEach(() => {
router = { navigate: jasmine.createSpy('navigate') };
snackbar = { showToast: jasmine.createSpy('showToast') };
userService = { signup: (email, pass) => null };
TestBed.configureTestingModule({
providers: [
{ provide: Router, useValue: router },
{ provide: UserService, useValue: userService },
{ provide: MdlSnackbarService, useValue: snackbar }
]
});;
});
现在,在您的测试中,您可以控制UserService
执行的操作,即返回成功的承诺,或返回错误承诺。通过这种方式,您可以测试组件对两种情况的反应。
it('should navigate on success', async(() => {
spyOn(userService, 'signup').and.returnValue(Promise.resolve());
component.signup();
fixture.whenStable().then(() => {
expect(router.navigate).toHaveBeenCalledWith(['/app/home']);
})
}))
it('should show toast on error', async(() => {
spyOn(userService, 'signup').and.returnValue(Promise.reject('error'));
component.signup();
fixture.whenStable().then(() => {
expect(snackbar.showToast).toHaveBeenCalledWith('error');
})
}))
这基本上是你想要测试组件以及它如何与这些服务交互的方式。
就错误Error: No component factory found for MdlSnackbarComponent.
而言,您需要在测试床declarations
中添加该组件,就像您需要的任何其他组件一样。如果您不想这样做,只需通过使用相同的选择器创建一个虚拟组件来模拟该组件,并将该组件添加到declarations
。