我的Angular项目中有一个breadcrumbs组件,你传入一个回调函数,当点击面包屑时会调用它。
用户传入一个对象,该对象包含用于呈现面包屑的信息,以及单击面包屑时的回调。
回调被添加到面包屑的onclick
事件中,并在用户点击一个时被调用。
<li *ngFor="let breadcrumb of breadcrumbs">
<span (click)="breadcrumb.callback()">{{breadcrumb.title}}</span>
</li>
这是我尝试过的:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [BreadcrumbsTestComponent, Breadcrumbs]
});
}));
it('should call given callback when breadcrumb is clicked', async(() => {
const fixture = TestBed.createComponent(BreadcrumbComponent);
fixture.detectChanges();
const breadcrumbElements = fixture.nativeElement.querySelectorAll('.breadcrumb');
breadcrumbElements.forEach(breadcrumb => {
breadcrumb.click();
fixture.whenStable().then(() => {
expect(breadcrumb.callback).toHaveBeenCalled();
});
});
}));
const breadcrumbs = [
{
title: 'First Page',
path: '/first',
current: false,
callback: jasmine.createSpy('callback')
}, {
title: 'Second Page',
path: '/second',
current: true,
callback: jasmine.createSpy('callback')
}
];
@Component({
template: `<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>`
})
class BreadcrumbsTestComponent {
breadcrumbs = breadcrumbs;
}
如何测试我的Jasmine测试中是否调用了回调?
感谢。
答案 0 :(得分:1)
(我回答了我所学到的东西,所以它可能不对,但这对我来说是合乎逻辑的,所以在这里!)
进行单元测试时,您应该测试您编写的代码是否按预期工作。这样做是为了防止在进行修改时产生副作用。
在您的情况下,您正在做的是测试框架是否正在执行其工作(发生事件)。
我相信这不是你应该做的:这种测试将用于e2e测试,你应该从一端(前端)到另一端(后端)进行测试。
这意味着如果我是你,我只会测试面包屑的函数callback
是否符合预期。
让我们假设它使面包屑闪烁:如果您测试面包屑是否闪烁,您将进行有用的测试。
因为如果有一天,你决定改变颜色而不是眨眼,那么你的测试会产生错误
同时,如果你想测试函数确实被调用,即使你彻底改变了回调的逻辑,测试也会通过。
我的底线是什么:测试回调的功能,而不是它的名字。
我希望这会有所帮助。
答案 1 :(得分:0)
您使用create spy是正确的。在这种情况下,您还可以省略create spy中的名称。它在你的测试中不起作用吗?
您可以更改的是不创建测试组件并直接测试面包屑组件。在这种情况下,我认为你不需要一个包装器组件,它只会使事情复杂化。然后测试看起来像这样:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { BreadcrumbsComponent } from './breadcrumbs.component';
import { Breadcrumb } from '../breadcrumb/breadcrumb';
import { By } from '@angular/platform-browser';
describe('BreadcrumbsComponent', () => {
let component: BreadcrumbsComponent;
let fixture: ComponentFixture<BreadcrumbsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BreadcrumbsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BreadcrumbsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should call given callback when breadcrumb is clicked', async(() => {
const breadcrumbs: Breadcrumb[] = [
{
title: 'First Page',
path: '/first',
current: false,
callback: jasmine.createSpy()
}, {
title: 'Second Page',
path: '/second',
current: true,
callback: jasmine.createSpy()
}
];
component.breadcrumbs = breadcrumbs;
fixture.detectChanges();
const breadcrumbElements = fixture.debugElement.queryAll(By.css('span'));
breadcrumbElements.forEach(breadcrumb => {
breadcrumb.nativeElement.click();
});
fixture.whenStable().then(() => {
breadcrumbs.forEach(breadcrumb => {
expect(breadcrumb.callback).toHaveBeenCalledTimes(1);
});
});
}));
});
我使用第一个框中的代码作为面包屑组件的代码,这就是为什么我在测试中查询span元素以单击它们的原因。