所以我试图在没有生命周期挂钩的组件上编写测试。
问题是我不知道何时直接像这样分配一个没有生命周期挂钩的值,我不知道何时准确调用它以及为什么在组件初始化时不调用它
component.ts
export class MainNavComponent {
isLoggedIn: boolean = this.authService.isLoggedIn;
user: User;
isHandset$: Observable<boolean> =
this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches)
);
constructor(private breakpointObserver: BreakpointObserver,
public authService: AuthService) {
//check logged in user
this.authService.user$.subscribe(res => {
if(res) {
this.isLoggedIn = true;
this.user = res;
} else {
this.isLoggedIn = false;
}
})
}
}
component.spec.ts
describe('MainNavComponent', () => {
let component: MainNavComponent;
let fixture: ComponentFixture<MainNavComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
MainNavComponent,
FooterComponent
],
imports: [
MaterialImportsModule,
RouterTestingModule.withRoutes([]),
HttpClientModule,
AngularFireModule.initializeApp(environment.firebase, 'my-app-name'),
AngularFirestoreModule,
AngularFireStorageModule,
AngularFireAuthModule,
BrowserAnimationsModule
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MainNavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('assing return if user is logged in and assign it to isLoggedIn', () => {
let service: AuthService = TestBed.get(AuthService);
spyOn(service, 'isLoggedIn').and.returnValue(true);
expect(component.isLoggedIn).toBeTruthy();
});
});
记录的消息
期望假为真。
答案 0 :(得分:1)
您应该将服务分配转移到beforeEach()方法,并将测试用例添加到fakeAsync()范围。然后,您将使用tick()模拟异步任务的时间流逝。
beforeEach(() => {
fixture = TestBed.createComponent(MainNavComponent);
component = fixture.componentInstance;
service: AuthService = TestBed.get(AuthService); //shift service to beforeEach()
fixture.detectChanges();
});
...
it('assing return if user is logged in and assign it to isLoggedIn', fakeAsync(() => {
spyOn(service, 'isLoggedIn').and.returnValue(true);
tick(); //simulate passage of time that api call went through;
fixture.detectChanges(); //trigger change detection in Angular to ensure class's isLoggedIn is updated
expect(service.isLoggedIn).toHaveBeenCalled();
expect(component.isLoggedIn).toBeTruthy();
}));
关于tick():https://angular.io/guide/testing#the-tick-function
调用tick()会模拟时间的流逝,直到所有未完成的异步活动结束为止
第二点,建议不要使用构造函数初始化服务调用。相反,它应该在ngOnInit()中完成。这是为了确保一致性并防止模板中的绑定错误。
取自Difference between Constructor and ngOnInit:
大多数情况下,我们使用ngOnInit进行所有初始化/声明,并避免某些东西在构造函数中起作用。构造函数应仅用于初始化类成员,而不应执行实际的“工作”。
因此,您应该使用构造函数()来设置依赖注入,而无需过多设置。 ngOnInit()是“开始”的更好位置-它是解析组件绑定的位置/时间。
答案 1 :(得分:1)
根据我的看法,您错误地spying
。
创建一个Mock
为
export class AuthServiceMock{
isLoggedIn = false;
user$ = new BehaviorSubject<any>({user: 'Hero'});
}
和spec
文件中的
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
MainNavComponent,
FooterComponent
],
imports: [
MaterialImportsModule, ..........
],
providers: [{provide: AuthService, useValue: AuthServiceMock}] // add this
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MainNavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should have isLoggedIn as "true" and "user" as defined ', () => {
expect(component.user).toBeDefined(); // or use "toEqual"
expect(component.isLoggedIn).toBeTruthy();
});
});