我正在尝试为调用router.navigate()
的组件编写一些测试,但是在声明路由时遇到了错误。我已经阅读了很多东西,并尝试了所有方法,但是它们都会导致某些错误或其他错误。我正在使用Angular 4.0.0。
零件:
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
constructor(
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private formBuilder: FormBuilder,
private jwtService: JwtService,
private router: Router,
private storageService: StorageService
) { ... }
ngOnInit() {
}
private login(formData: any): void {
const credentials: any = {
email: formData.controls.email.value,
password: formData.controls.password.value
};
this.authService.login(credentials).subscribe(res => {
this.activatedRoute.params.subscribe(params => {
if (params.returnUrl) {
this.router.navigate([params.returnUrl]);
} else {
this.router.navigate(['/dashboard']);
}
});
}, error => { ... });
}
}
测试:
describe('LoginComponent', () => {
let component: any;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
SharedModule,
RouterTestingModule
],
providers: [{
provide: AuthService,
useClass: MockAuthService
}, {
provide: JwtService,
useClass: MockJwtService
}, {
provide: StorageService,
useClass: MockStorageService
}],
schemas: [ NO_ERRORS_SCHEMA ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('login', () => {
it('should call router.navigate with the dashboard route if the login is successful', () => {
spyOn(component.router, 'navigate');
component.authService.login.and.returnValue(Observable.of({ access_token: 'fake_token' }));
component.login(component.loginForm);
expect(component.router.navigate).toHaveBeenCalledWith(['/dashboard']);
});
});
});
这一切给了我以下错误:
zone.js:569未处理的承诺拒绝:无法匹配任何路由。网址段:“仪表板”
因此,我从那里开始研究使用
withRoutes
添加路线。我不喜欢我需要包含DashboardComponent
,因为似乎应该为此提供一些模拟/空白的组件,尤其是因为我不想实际导航并加载其他路线,但我找不到任何东西像那样:TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
SharedModule,
RouterTestingModule.withRoutes([{
path: 'dashboard',
component: DashboardComponent
}])
],
...
})
.compileComponents();
但是,这只是给我一个新的错误:
组件DashboardComponent不是任何NgModule的一部分,或者该模块尚未导入到您的模块中。
所以我认为也许我需要声明
DashboardComponent
,所以我将其添加到了声明数组中:TestBed.configureTestingModule({
declarations: [ LoginComponent, DashboardComponent ],
..
})
.compileComponents();
但是,这只会导致另一个错误:
未处理的承诺拒绝:找不到要加载“ DashboardComponent”的主要出口
在这一点上,似乎必须采用一种更简单的方法来完成此操作,因为这是一个非常常见的场景,但是我已经尝试了其他人说的所有使用方法,而所有方法都将进一步拖延这个兔子漏洞。
最佳答案
事实证明该解决方案非常简单...
只需添加RouterTestingModule就可以了,只需要监视所有测试中的router.navigate即可防止它们尝试实际导航到另一条路线。
describe('LoginComponent', () => {
let component: any;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
SharedModule,
RouterTestingModule // This provides the mock router, location and routerLink
],
providers: [{
provide: AuthService,
useClass: MockAuthService
}, {
provide: JwtService,
useClass: MockJwtService
}, {
provide: StorageService,
useClass: MockStorageService
}],
schemas: [ NO_ERRORS_SCHEMA ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
spyOn(component.router, 'navigate'); // This prevents every test from calling the real router.navigate which means I don't need to add routes to RouterTestingModule
});
describe('login', () => {
it('should call router.navigate with the dashboard route if the login is successful', () => {
spyOn(component.router, 'navigate');
component.authService.login.and.returnValue(Observable.of({ access_token: 'fake_token' }));
component.login(component.loginForm);
expect(component.router.navigate).toHaveBeenCalledWith(['/dashboard']);
});
});
});