我是Angular测试的新手,但遇到了问题。
第一个问题是将变量username
放入一个组件中,该组件用于将登录的用户名显示在HTML页面中:
这是测试文件:
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
let app;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HeaderComponent, DialogListConfigurationComponent, DialogConfirmNewConfigurationComponent ],
providers: [ MessageService, JwtHelperService, AuthService ],
imports: [ DialogModule, MenubarModule, FontAwesomeModule, RouterTestingModule, TreeModule, HttpClientTestingModule, JwtModule.forRoot({
config: {
tokenGetter: () => {
return sessionStorage.getItem(environment.tokenName);
},
//Exclude this URL from JWT (doesn't add the authentication header)
blacklistedRoutes: [
'/api/login',
]
}
}), ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
组件是这样的:
export class HeaderComponent implements OnInit {
@Output() sidebarEvent = new EventEmitter();
@Output() clickOkButtonListConfigurationsEvent = new EventEmitter();
username: String = this.authService.decodeToken.username;
items = [] as MenuItem[];
dialogListConfigurationVisible: boolean = false;
faUserCircle = faUserCircle;
defaultConfigurations: Configuration[];
configurationCreated: boolean = false;
dialogConfirmCreationVisible: boolean = false;
constructor(private configurationService: ConfigurationService, private authService: AuthService) { }
ngOnInit() {
...
}
身份验证服务方法:
get decodeToken(): Jwt {
return this.jwtHelper.decodeToken(this.getSessionToken);
}
should create
测试失败,TypeError: Cannot read property 'username' of null
答案 0 :(得分:3)
您需要模拟您的AuthService ,因为这是组件测试。
您可以通过在模块初始化代码中提供一个对象来实现
TestBed.configureTestingModule({
declarations: [ HeaderComponent, DialogListConfigurationComponent, DialogConfirmNewConfigurationComponent ],
providers: [
MessageService,
JwtHelperService,
{provide: AuthService, useClass: AuthServiceMock} ],
imports: [ DialogModule, MenubarModule, FontAwesomeModule, RouterTestingModule, TreeModule, HttpClientTestingModule, JwtModule.forRoot({
config: {
tokenGetter: () => {
return sessionStorage.getItem(environment.tokenName);
},
//Exclude this URL from JWT (doesn't add the authentication header)
blacklistedRoutes: [
'/api/login',
]
}
}), ]
})
.compileComponents();
AuthServiceMock
类应实现与原始接口相同的接口。可能是这样的:
export class AuthServiceMock {
// ...
decodeToken: {
username: 'testUser'
};
}
然后,如果您不想在模拟中设置默认值,请在创建组件之前设置模拟类。
注意::您可以在不创建模拟的情况下完成最后一步,但这会破坏测试中关注点的分离。
beforeEach(() => {
let authServiceMock: AuthServiceMock = TestBed.get(AuthService);
authServiceMock.decodeToken = { username: 'anotheruser' };
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
这应该允许HeaderComponent
运行this.authService.decodedToken.username
行。
作为准则:需要模拟依赖于外部数据的依赖项。
如果以前在测试模块初始化中包括了原始AuthService
的依赖项,那么您也可以删除它们。例如,如果JwtHelperService
仅在内部用于AuthService
,则测试模块可以排除该提供程序。
答案 1 :(得分:0)
在@Thatkookooguy答案中,我遇到了问题,并将这两个原始值添加到beforeEach中,避免使用模拟对象
const authService: AuthService = TestBed.get(AuthService);
authService.saveToken("token string");