angular - 测试时在 *ngIf 语句中找不到按钮,因为语句涉及模拟类
问题描述
我正在构建一个应用程序,人们可以在其中使用 Angular 中的 Github 进行身份验证。我已经建立了一个按钮来做到这一点。尝试测试此按钮时,测试似乎找不到该按钮。我认为它与 *ngIf 语句有关。
login.component.spec.ts:
class MockAuthService implements Partial<AuthService> {
isAuthenticated() {
return 'Mocked';
}
loginwithGithubProvider() {
return new Promise((resolve, reject) => resolve());
}
logout(): Promise<boolean | Observable<never> | never> {
return new Promise(function(resolve, reject) { resolve(); });
}
}
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let componentService: AuthService;
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
const ghServiceSpy = jasmine.createSpyObj('GithubService', ['methodName']);
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MatCardModule,
AngularFireModule.initializeApp(environment.firebase),
RouterModule.forRoot([{path: '', component: LoginComponent}]),
],
declarations: [
LoginComponent
],
providers: [
AuthService,
AngularFirestore,
AngularFireAuth,
HttpClient,
HttpHandler
]
});
TestBed.overrideComponent(LoginComponent, {
set: {
providers: [
{provide: AuthService, useClass: MockAuthService},
{provide: Router, useValue: routerSpy},
{provide: GithubService, useValue: ghServiceSpy},
]
}
});
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
componentService = fixture.debugElement.injector.get(AuthService);
}));
it('Logginbutton calls signInWithGithub', async(() => {
spyOn(component, 'signInWithGithub');
const button = fixture.debugElement.nativeElement.querySelector('#signInWithGithub');
button.click();
fixture.whenStable().then(() => {
expect(component.signInWithGithub).toHaveBeenCalled();
});
}));
login.component.html:
<div *ngIf="authService.isLoggedIn; else loginTemplate">
<h1>Welcome {{authService?.username}}</h1>
<img src="{{ authService?.userDetails?.photoURL }} ">
<br />
<button mat-flat-button class="btn-github" id="logout" (click)="logout()">
<i class="fab fa-github"></i> Stop authentication Github
</button>
</div>
<ng-template #loginTemplate>
<h1>FullProjectCloner</h1>
<button mat-flat-button class="btn-github" id="signInWithGithub" (click)="signInWithGithub()">
<i class="fab fa-github"></i> Authenticate with github
</button>
<p class="authError">{{this?.loginError}}</p>
</ng-template>
我得到的错误:
TypeError: Cannot read property 'click' of null
解决方案
问题是您已经设置了所有内容,但在测试之前没有调用让 Angular 实际渲染任何内容所需的生命周期更改。
简单的解决方法是fixture.detectChanges()
在您 spyOn 组件后调用。
我把它放在一个Stackblitz中,以确保它对你有用。在那个 Stackblitz 中,只需注释掉fixture.detectChanges()
,你就会看到问题。
这是 Stackblitz 的规范:
it('Logginbutton calls signInWithGithub', async(() => {
spyOn(component, 'signInWithGithub');
fixture.detectChanges();
const button = fixture.debugElement.nativeElement.querySelector('#signInWithGithub');
button.click();
expect(component.signInWithGithub).toHaveBeenCalled();
}));
您会注意到我也删除了对的调用,whenStable()
因为这也不需要。
推荐阅读
- oracle - 有没有办法在 PL SQL 中本地缓存和过滤表?
- angular - Angular 9 - 提供了重复的列定义名称 - detailExpand
- django - 使用变量返回重定向
- c - 切换案例以在 c 中找到最大值或相等不起作用
- django - get_context_data 方法 Django
- docker - 创建 docker 服务不等于创建 docker 容器
- java - Java Path 如何转换为例如 InputStream
- reactjs - 对于用列表表示的状态,React State 仍然是不可变的
- javascript - 尝试根据过滤器选择用字符串值填充数组,并通过将数组与记录属性的字符串值进行比较来过滤记录
- azure - IoT 中心 - 如何注册生命周期事件 - 断开连接和连接?