假设我有以下组件:
@Component({
selector: 'app-dumb',
template: '<button (click)="increment()">Increment</button>'
})
export class DumbComponent {
@Output() onIncrement = new EventEmitter<void>();
increment() {
this.onIncrement.emit();
}
}
我使用的是Angular Testing Library,我的目标是点击按钮并断言给定的输出函数已经被调用。
该项目使用的是因果报应/茉莉花,加上玩笑似乎并不简单。
以下描述了我能够检查所需内容的唯一方法,但我希望避免监视componentInstance
,而是注入我想要监视的thing
。
it("emits an event when the increment button is clicked", async () => {
const { fixture } = await render(DumbComponent);
spyOn(fixture.componentInstance.onIncrement, 'emit');
await clickIncrementButton();
expect(fixture.componentInstance.onIncrement.emit).toHaveBeenCalledTimes(1);
})
我尝试使用jasmine.createSpy
,但它似乎不是要注入的有效类型。
const onIncrement = createSpy();
await render(DumbComponent, {
componentProperties: {
onIncrement: onIncrement
}
})
知道吗?
长话短说,我只能在其中注入两个things
,它们要么是事件发射器的实例,要么是mock/spy。
前者可以通过以下方式实现:
// solution 1
it("emits an event when the increment button is clicked", async () => {
let emitted = false;
const onIncrement = new EventEmitter<void>();
await render(DumbComponent, {
componentProperties: {
onIncrement: onIncrement
}
});
onIncrement.subscribe(() => emitted = true)
await clickIncrementButton();
expect(emitted).toBeTrue();
})
话虽如此,正如jonrsharpe所指出的,输出是组件公共接口的一部分,因此实际上我们可以通过直接订阅公共属性来实现同样的目的:
// solution 2
it("emits an event when the increment button is clicked", async () => {
let emitted = false;
const {fixture} = await render(DumbComponent);
fixture.componentInstance.onIncrement.subscribe(() => emitted = true)
await clickIncrementButton();
expect(emitted).toBeTrue();
})
最后,我们还可以通过以下方式注入间谍(茉莉花(:
// solution 3
it("emits an event when the increment button is clicked", async () => {
const emit = createSpy()
await render(DumbComponent, {
componentProperties: {
onIncrement: {
emit: emit
} as any
}
});
await clickIncrementButton();
expect(emit).toHaveBeenCalledTimes(1)
})
我个人更喜欢真实的例子而不是模拟,特别是我可能会坚持第一个解决方案。
也就是说,第一个和第二个解决方案是等效的,它们都与公共接口耦合,所以如果属性的名称确实发生了更改,那么这两个测试都需要修复。
希望这能有所帮助!