我正在使用Karma处理Angular 2的单元测试用例,我遇到了一个函数,我在下面运行测试
expect(component.subscribeToEvents()).toBeTruthy();
我查看我的覆盖代码,测试文件中的行似乎没有覆盖订阅内的任何内容。我已经尝试使用MockBackend模拟服务函数内的api调用,但我不确定如何对订阅对象进行模拟,有人可以帮助我吗?
以下是test.component.ts
subscribeToEvents() {
this.subscription = this.czData.$selectedColorZone
.subscribe(items => {
this.resourceLoading = true;
if (!this.resourceData || (this.resourceData && this.resourceData.length === 0)) {
this.settings.layout.flypanel.display = false;
this.getAllResources(this.pagination.start, this.pagination.size);
}
else {
this.pagination.start = 1;
this.pagination.end = this.pagination.size;
this.getAllResources(1, this.pagination.size);
this.settings.layout.flypanel.display = true;
}
});
return true;
}
答案 0 :(得分:3)
您无法执行此操作,因为订阅是异步解析的。因此,在解析异步任务之前,同步测试已完成。
如果你想要的只是覆盖范围,你可以进行测试async
。这将导致Angular测试区等到异步任务解决,然后再完成测试
import { async } from '@angular/core/testing';
it('..', async(() => {
component.subscribeToEvents();
}))
你不能在这里尝试任何东西,因为在任务解决时没有回调钩子。所以这真是一个毫无意义的考验。它会给你报道,但你实际上并没有测试任何东西。例如,您可能希望测试在解析订阅时设置变量。
根据提供的代码,我要做的只是模拟服务,并使其成为同步。你怎么能这样做?我们可以使模拟类似
class CzDataSub {
items: any = [];
$selectedColorZone = {
subscribe: (callback: Function) => {
callback(this.items);
}
}
}
然后在测试中配置它
let czData: CzDataStub;
beforeEach(() => {
czData = new CzDataStub();
TestBed.configureTestingModule({
providers: [
{ provide: CzData, useValue: czData }
]
})
})
现在,在您的测试中,您不需要将其设为async
,只需在模拟上设置items
属性即可提供您想要的任何值,订阅者将获得它
it('..', () => {
czData.items = something;
component.subscribeToEvents();
expect(component.settings.layout.flypanel.display).toBe(false);
})
我在写这篇文章时觉得我半睡半醒。以上陈述之一是不正确的
你不能在这里尝试任何东西,因为在任务解决时没有回调钩子。
这不完全正确。这是fixture.whenStable()
的用途。例如,如果这是您的服务
class CzData {
_value = new Subject<>();
$selectedColorZone = this._value.asObservable();
setValue(value) {
this._value.next(value);
}
}
然后这就是你如何进行测试
let czData: CzData;
let fixture: ComponentFixture<YourComponent>;
let component: YourComponent;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ CzData ],
declarations: [ YourComponent ]
});
fixture = TestBed.createComponent(YourComponent);
component = fixture.componentInstance;
czData = TestBed.get(czData);
})
it('..', async(() => {
component.subscribeToEvents();
czData.setValue(somevalue);
fixture.whenStable().then(() => {
expect(component.settings.layout.flypanel.display).toBe(false);
})
}))
我们使用fixture.whenStable()
来等待异步任务完成。
这并不是说使用模拟是错误的。很多时候,使用模拟将是要走的路。我只是想纠正我的陈述,并说明如何做到这一点。
答案 1 :(得分:0)
请考虑如何测试角度输出,因为在测试过程中订阅了它们:https://angular.io/guide/testing#clicking
it('should raise selected event when clicked (triggerEventHandler)', () => {
let selected: Hero;
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
heroDe.triggerEventHandler('click', null);
expect(selectedHero).toBe(expectedHero);
});
所以尝试:
const expectedItem = {}; // mock the expected result from 'subscribeToEvents'
it('should raise selected event when clicked (triggerEventHandler)', () => {
let selectedItem: any; // change to expected type
component.subscribeToEvents.subscribe((item: any) => selectedItem = item);
// fixture.detectChanges(); // trigger change detection if necessary here, depending on what triggers 'subscribeToEvents'
expect(selectedItem).toBe(expectedItem);
});