Angular5中ActivatedRoute queryParams订阅逻辑单元测试问题
搞定Angular组件中ActivatedRoute queryParams的测试问题
我来帮你梳理下问题所在,你现在的测试失败主要是因为用同一个mock对象模拟了三个完全不同的服务,导致属性混乱,而且没有正确模拟ActivatedRoute.queryParams的Observable结构。咱们一步步来修正:
首先,拆分模拟服务,别混用
你之前把Router、ActivatedRoute、AuthService都塞到同一个mockService里,这肯定不对——比如Router根本不需要queryParams,ActivatedRoute也没有navigate方法,这种混用会让你的模拟完全不符合实际服务的行为。咱们给每个服务单独做mock:
// 专门模拟Router,只保留它需要的navigate方法 const mockRouter = { navigate: jasmine.createSpy('navigate') }; // 专门模拟AuthService,只保留isAuthenticated方法 const mockAuthService = { isAuthenticated: jasmine.createSpy('isAuthenticated') }; // 专门模拟ActivatedRoute,重点是queryParams得是Observable类型 const mockActivatedRoute = { queryParams: new Observable() };
然后,针对每个测试场景动态设置Observable值
queryParams是个Observable,所以你需要在每个测试用例里给它传入对应的值,让订阅逻辑能触发:
场景1:验证有params['data']时调用handle方法
先把组件的handle方法spy起来,方便后续验证,然后让queryParams发出包含data的参数:
it('should trigger handle when params contains data', () => { // Spy组件的handle方法,用来验证是否被调用 spyOn(component, 'handle'); // 让queryParams发出带data的参数对象 mockActivatedRoute.queryParams = of({ data: 'test-value' }); component.ngOnInit(); expect(component.handle).toHaveBeenCalledWith('test-value'); });
场景2:验证无参数且已认证时跳转home页
先让AuthService返回已认证状态,再让queryParams发出空参数,最后验证跳转方法是否被调用:
it('should navigate to home when no params and user is authenticated', () => { // 设置auth服务返回已认证 mockAuthService.isAuthenticated.and.returnValue(true); // 让queryParams发出空参数对象 mockActivatedRoute.queryParams = of({}); component.ngOnInit(); expect(mockRouter.navigate).toHaveBeenCalledWith(['/home']); });
最后,修正TestBed的配置
把拆分好的mock对象分别注入对应的服务,确保依赖注入正确:
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [TestComponent], providers: [ { provide: Router, useValue: mockRouter }, { provide: ActivatedRoute, useValue: mockActivatedRoute }, { provide: AuthService, useValue: mockAuthService } ] }).compileComponents(); fixture = TestBed.createComponent(TestComponent); component = fixture.componentInstance; }));
补充说明:之前的错误原因
- 第一个报错
TypeError: this.route.queryParams.subscribe is not a function:因为你把queryParams设成了spy,而实际ActivatedRoute.queryParams是Observable,它自带subscribe方法,你的mock没有这个结构,自然报错。 - 第二个报错
Expected spy navigate to have been called...:一方面是混用mock导致属性冲突,另一方面是你没让queryParams的Observable发出值,订阅里的逻辑根本没执行,所以跳转方法当然没被调用。
别忘了导入RxJS的of操作符:
import { of } from 'rxjs';
这样调整后,你的两个测试场景应该都能正常通过了~
内容的提问来源于stack exchange,提问作者BoonZ
相关产品推荐
相关产品推荐

