我有一个单元测试,我想测试一个函数是否在按钮点击时被调用。但我一直收到这个错误。Expected spy archive to have been called.
我不明白为什么它不能工作。
是不是我遗漏了什么或做错了什么?关于上下文,请看下面的代码。
这是我的测试
it('should call archive function on button click', async(() => {
spyOn(component, 'archive');
fixture.detectChanges();
component.project = rh.getProjects(1)[0];
dh.clickButton('Archive');
fixture.detectChanges();
expect(component.archive).toHaveBeenCalled();
}));
这就是dh又名DOMHelper。
clickButton(buttonText: string) {
this.findAll('button').forEach(button => {
const buttonElement: HTMLButtonElement = button.nativeElement;
if (buttonElement.textContent === buttonText) {
buttonElement.click();
}
});
}
findAll(tagName: string) {
return this.fixture.debugElement
.queryAll(By.css(tagName));
}
这是html
<td data-label="Title">{{ project.title }}</td>
<td data-label="Owner">{{ getOwnerName(project.owner) }}</td>
<td data-label="Actions">
<button class="btn btn-primary" (click)="dashboard">Dashboard</button>
<button *ngIf="authService.firebaseAuth.auth.currentUser.uid == project.owner" class="btn btn-primary" (click)="archive">Archive</button>
</td>
这是component.ts文件
import { Component, OnInit, Input } from '@angular/core';
import { Project } from 'src/app/models/project';
import { AuthService } from 'src/app/services/auth.service';
import { ProjectService } from 'src/app/services/project.service';
import { Router } from '@angular/router';
@Component({
selector: 'tr[app-joined-project-item]',
templateUrl: './joined-project-item.component.html',
styleUrls: ['./joined-project-item.component.css'],
})
export class JoinedProjectItemComponent implements OnInit {
@Input() public project: Project;
constructor(public authService: AuthService, public projectService: ProjectService, private router: Router) {}
ngOnInit(): void {
}
archive() {
this.projectService.updateArchivedStatusProject(this.project);
}
dashboard() {
this.router.navigate(['/projects/' + this.project.id + '/dashboard'])
}
getOwnerName(userId: string) {
return Object.values(this.project.members).find((member: any) => member['userId'] === userId)['name'];
}
}
更新
当我测试它时,我检查服务函数是否被调用,我得到以下错误。Expected spy updateArchivedStatusProject to have been called with: *Project Object* but it was never called.
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [JoinedProjectItemComponent],
providers: [
{ provide: ProjectService, useClass: MockProjectService },
{ provide: AuthService, useClass: MockAuthService },
{ provide: Router, useValue: routerSpy }
]
}).compileComponents();
}));
it('should call archive function on button click', async(() => {
spy = spyOn(TestBed.get(ProjectService), 'updateArchivedStatusProject');
fixture.detectChanges();
component.project = rh.getProjects(1)[0];
dh.clickButton('Archive');
fixture.detectChanges();
expect(spy).toHaveBeenCalledWith(rh.projects[0]);
}));
我想你在点击处理程序中缺少了括号。应该是:
<button (...) (click)="archive()">Archive</button>
EDIT:
事实上,你认为这是测试的错误,而不是一个实际的简单错误,这表明你不信任你的测试。这可能发生在应用程序正常工作的情况下,当它们经常失败的时候。这说明你写测试的方式可能有问题。
我给出的一个建议是,让你在测试中使用的工具尽可能的明确。例如 clickButton
可以改写成这样的内容:
clickButton(buttonText: string) {
const foundButtons = this.findAll('button')
.map(button => button.nativeElement)
.filter(button => button.innerText === buttonText);
if (foundButtons.length !== 1) {
fail(`Expected exactly one button with text "${buttonText}" but found ${foundButtons.length}`);
}
foundButtons[0].click();
}