英文:
How to unit test Rxjs combineLatest?
问题
我的组件的ngOnInit
方法如下:
public ngOnInit() {
this.ctrSubscription = combineLatest(this.route.queryParams, this.tags$).subscribe(async params => {
if (Object.keys(params[0]).length > 0) {
this.initView({ ...params[0] });
}
if (Object.keys(params[1]).length > 0) {
this.wsTags = Object.values(params[1]);
}
if (params[0] && this.wsTags.length > 0) {
this.searchWs({ ...params[0] }.q);
this.pruneData();
}
});
}
这是我如何进行测试的部分:
it('should perform search and load the results', fakeAsync(() => {
TestBed.get(ActivatedRoute).queryParams = of({ q: 'test' });
const initSpy = spyOn<any>(component, 'initView').and.callThrough();
const subSpy = spyOn<any>(component.tags$, 'subscribe');
component.wsTags = ensureState(mockTags as any);
flushMicroTasks();
fixture.detectChanges();
flushMicroTasks();
expect(initSpy).toHaveBeenCalledWith({ q: 'test' });
expect(subSpy).toHaveBeenCalled();
expect(component.wsTags).toBe(Object.values(mockTags));
}));
间谍(spies)根本没有被调用。我在运行测试时设置了断点,以了解是否正确传递了值,我能够正确捕获传递的查询参数,但条件仍然失败。
我尝试查看文档以更好地理解,并在 Stack Overflow 上查看各种类似的问题,但我无法解决它。我对编写单元测试相对不熟悉,所以任何帮助将不胜感激。谢谢。
英文:
My component's ngOnInit does this
public ngOnInit() {
this.ctrSubscription = combineLatest(this.route.queryParams, this.tags$).subscribe(async params => {
if (Object.keys(params[0]).length > 0) {
this.initView({ ...params[0] });
}
if (Object.keys(params[1]).length > 0) {
this.wsTags = Object.values(params[1]);
}
if (params[0] && this.wsTags.length > 0) {
this.searchWs({ ...params[0] }.q);
this.pruneData();
}
});
}
And this is how i am testing it
it('should perform search and load the results', fakeAsync(() => {
TestBed.get(ActivatedRoute).queryParams = of({ q: 'test' });
const initSpy = spyOn<any>(component, 'initView').and.callThrough();
const subSpy = spyOn<any>(component.tags$, 'subscribe');
component.wsTags = ensureState(mockTags as any);
flushMicroTasks();
fixture.detectChanges();
flushMicroTasks();
expect(initSpy).toHaveBeenCalledWith({ q: 'test' });
expect(subSpy).toHaveBeenCalled();
expect(component.wsTags).toBe(Object.values(mockTags));
}));
the spys are not getting called at all.I put a breakpoint when running tests to know if the value is passing or not , and i was able to catch the query params being passed correctly but still the if fails.
I tried going through the docs to understand better and also various similar questions here on stack overflow, i couldn't able to solve it. I am fairly new to writing unit tests, so any help will be appreciated. Thanks.
答案1
得分: 1
一个潜在的问题是你在it
块内部对ActivatedRoute
进行了模拟。这太晚了,你的ngOnInit
在第一次compileComponents
之后的detectChanges
之后运行。
在配置测试模块时,请尝试:
describe('测试描述', () => {
let component: YourComponent;
let activatedRoute: ActivatedRoute;
let fixture: ComponentFixture<YourComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [YourComponentToTest,
// 如果需要,可以添加其他声明。
],
providers: [
{
provide: ActivatedRoute,
useValue: {
queryParams: of({ q: 'test' }),
},
},
],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(YourComponentToTest);
component = fixture.componentInstance;
activatedRoute = TestBed.get(ActivatedRoute);
// ngOnInit 现在已经运行 - 在第一次 detectChanges 之后
fixture.detectChanges();
});
it('应该执行你想要的操作', () => {
// 你的安排、行动和断言。
});
})
确保this.tags$
也被初始化。
我是全程手写的,可能会有拼写错误。
英文:
One potential issue is that you're mocking ActivatedRoute
within the it
block. This is too late, your ngOnInit
runs after the first detectChanges
after compileComponents
.
When configuring your testing module, try:
describe('Put description of the test', () => {
let component: YourComponent;
let activatedRoute: ActivatedRoute;
let fixture: ComponentFixture<YourComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ YourComponentToTest,
// other declarations if need be.
],
providers: [
provide: ActivatedRoute,
useValue: {
queryParams: of({ q: 'test" }),
}
]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(YourComponentToTest);
component = fixture.componentInstance;
activatedRoute = TestBed.get(ActivatedRoute);
// ngOnInit is ran now -- after the first detectChanges
fixture.detectChanges();
});
it('should do what you want', () => {
// your arrange, act, and assertions.
});
})
Make sure this.tags$
is initialized as well.
I did all of this freehand so there may be typo(s).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论