在不监视组件实例的情况下测试 Angular 输出
Testing Angular Output without spying on the component instance
假设我有以下组件:
@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,我的 objective 是点击按钮并断言给定的输出函数已被调用。
项目正在使用karma/jasmine,添加jest好像不太直接
以下描述了我能够检查所需内容的唯一方法,但我想避免监视 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 所指出的,输出是组件 public 接口的一部分,因此实际上我们可以通过直接订阅 public 属性:
// 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();
})
最后我们还可以通过以下方式注入间谍(jasmine):
// 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)
})
我个人的偏好是真实实例而不是模拟,具体来说,我可能会坚持使用第一种解决方案。
也就是说,第一个和第二个解决方案是等效的,它们都与 public 接口耦合,因此如果 属性 的名称确实发生了变化,那么这两个测试都需要修复无论如何。
希望对您有所帮助!
假设我有以下组件:
@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,我的 objective 是点击按钮并断言给定的输出函数已被调用。
项目正在使用karma/jasmine,添加jest好像不太直接
以下描述了我能够检查所需内容的唯一方法,但我想避免监视 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 所指出的,输出是组件 public 接口的一部分,因此实际上我们可以通过直接订阅 public 属性:
// 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();
})
最后我们还可以通过以下方式注入间谍(jasmine):
// 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)
})
我个人的偏好是真实实例而不是模拟,具体来说,我可能会坚持使用第一种解决方案。
也就是说,第一个和第二个解决方案是等效的,它们都与 public 接口耦合,因此如果 属性 的名称确实发生了变化,那么这两个测试都需要修复无论如何。
希望对您有所帮助!