我正在尝试将单元测试添加到我的Angular 2应用中。在我的一个组件中,有一个带有(click)
处理程序的按钮。当用户单击该按钮时,将调用一个在.ts
类文件中定义的函数。该函数在console.log窗口中打印一条消息,说明该按钮已被按下。我目前的测试代码测试打印console.log
消息:
describe('Component: ComponentToBeTested', () => {
var component: ComponentToBeTested;
beforeEach(() => {
component = new ComponentToBeTested();
spyOn(console, 'log');
});
it('should call onEditButtonClick() and print console.log', () => {
component.onEditButtonClick();
expect(console.log).toHaveBeenCalledWith('Edit button has been clicked!);
});
});
但是,这只测试控制器类,而不是HTML。我并不想测试在调用onEditButtonClick
时发生日志记录;我还想测试当用户单击组件的HTML文件中定义的编辑按钮时调用onEditButtonClick
。我怎么能这样做?
答案 0 :(得分:62)
我的目标是检查' onEditButtonClick'当用户单击编辑按钮而不是仅检查正在打印的console.log时,将调用此方法。
您需要先使用Angular TestBed
设置测试。这样你就可以抓住按钮然后点击它。你将要做的是配置一个模块,就像你@NgModule
一样,仅用于测试环境
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
describe('', () => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ ],
declarations: [ TestComponent ],
providers[ ]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
});
}));
});
然后你需要监视onEditButtonClick
方法,点击按钮,然后检查方法是否被调用
it('should', async(() => {
spyOn(component, 'onEditButtonClick');
let button = fixture.debugElement.nativeElement.querySelector('button');
button.click();
fixture.whenStable().then(() => {
expect(component.onEditButtonClick).toHaveBeenCalled();
});
}));
这里我们需要运行async
测试,因为按钮单击包含异步事件处理,需要通过调用fixture.whenStable()
等待事件处理
另见:
答案 1 :(得分:33)
可以使用async
提供的fakeAsync
/ '@angular/core/testing'
函数测试事件,因为浏览器中的任何事件都是异步的并且被推送到事件循环/队列。
以下是使用fakeAsync
测试点击事件的一个非常基本的示例。
fakeAsync
函数通过在特殊fakeAsync
测试区中运行测试体来启用线性编码样式。
这里我正在测试click事件调用的方法。
it('should', fakeAsync( () => {
fixture.detectChanges();
spyOn(componentInstance, 'method name'); //method attached to the click.
let btn = fixture.debugElement.query(By.css('button'));
btn.triggerEventHandler('click', null);
tick(); // simulates the passage of time until all pending asynchronous activities finish
fixture.detectChanges();
expect(componentInstance.methodName).toHaveBeenCalled();
}));
以下是Angular docs所说的内容:
fakeAsync优于异步的主要优点是测试似乎是同步的。没有
取代then(...)
来破坏可见的控制流。承诺返回fixture.whenStable
已消失,由tick()
是的限制。例如,您无法在
内拨打XHR电话fakeAsync
答案 2 :(得分:1)
我正在使用 Angular 6 。我按照Mav55的回答进行了操作。但是我想确保fixture.detectChanges();
是否真的有必要,所以我删除它仍然有效。然后我删除tick();
以查看它是否有效并且确实有效。最后,我从fakeAsync()
包装中删除了测试,并且惊讶,它有效。
所以我最终得到了这个:
it('should call onClick method', () => {
const onClickMock = spyOn(component, 'onClick');
fixture.debugElement.query(By.css('button')).triggerEventHandler('click', null);
expect(onClickMock).toHaveBeenCalled();
});
它运作得很好。
答案 3 :(得分:0)
我遇到了类似的问题(详细解释如下),我使用jasmine-core: 2.52
函数解决了它(在tick
中)与原始setTimeout
函数相同(或更大)的毫秒数1}}来电。
例如,如果我有setTimeout(() => {...}, 2500);
(所以它会在2500毫秒后触发),我会调用tick(2500)
和来解决问题。
我在组件中的内容,作为对删除按钮的反应点击:
delete() {
this.myService.delete(this.id)
.subscribe(
response => {
this.message = 'Successfully deleted! Redirecting...';
setTimeout(() => {
this.router.navigate(['/home']);
}, 2500); // I wait for 2.5 seconds before redirect
});
}
她是我的工作测试:
it('should delete the entity', fakeAsync(() => {
component.id = 1; // preparations..
component.getEntity(); // this one loads up the entity to my component
tick(); // make sure that everything that is async is resolved/completed
expect(myService.getMyThing).toHaveBeenCalledWith(1);
// more expects here..
fixture.detectChanges();
tick();
fixture.detectChanges();
const deleteButton = fixture.debugElement.query(By.css('.btn-danger')).nativeElement;
deleteButton.click(); // I've clicked the button, and now the delete function is called...
tick(2501); // timeout for redirect is 2500 ms :) <-- solution
expect(myService.delete).toHaveBeenCalledWith(1);
// more expects here..
}));
P.S。有关fakeAsync
和测试中的一般异步的详细解释,请访问:a video on Testing strategies with Angular 2 - Julie Ralph, starting from 8:10, lasting 4 minutes :)
答案 4 :(得分:-1)
首先要检查按钮调用事件,我们需要监视在单击按钮后将被调用的方法 所以我们的第一行是spyOn 间谍方法有两个参数 1)组件名称 2)被监视的方法,即:'onSubmit'记住不要使用'()'仅名称 那么我们需要使按钮的对象被点击 现在我们必须触发事件处理程序,在该事件处理程序上添加点击事件 那么我们希望我们的代码一次调用Submit方法
it('should call onSubmit method',() => {
spyOn(component, 'onSubmit');
let submitButton: DebugElement =
fixture.debugElement.query(By.css('button[type=submit]'));
fixture.detectChanges();
submitButton.triggerEventHandler('click',null);
fixture.detectChanges();
expect(component.onSubmit).toHaveBeenCalledTimes(1);
});