使用ng-mocks时如何在特定测试中修改mock provider的取值?
问题核心原因
- 你自行定义了固定的
mockActivatedRoute字面量对象并通过useValue注入,MockInstance仅对ng-mocks托管的mock实例生效,对自定义的字面量对象不会生效。 - 你在最外层的
beforeEach中已经执行了MockRender完成组件初始化,嵌套describe中对provider的修改执行在组件初始化之后,自然不会更新已经生成的routeId。
可用解决方案
方案1:使用ng-mocks托管mock(推荐)
让ng-mocks接管ActivatedRoute的mock生成,配合MockInstance动态修改属性,同时将组件渲染逻辑后置到provider修改完成后执行:
describe('MyComponent', () => { MockInstance.scope('all'); beforeEach(() => { // 让ng-mocks生成mock实例,默认配置id为1 return MockBuilder(MyComponent, MyModule) .mock(ActivatedRoute, { snapshot: { params: { id: 1 } } }); }); // 抽离公共渲染方法,在provider配置完成后调用 function renderComponent() { fixture = MockRender(MyComponent); component = fixture.point.componentInstance; } it('should have an id of 1', () => { renderComponent(); expect(component.routeId).toEqual(1); }); describe('when it inits with a different id', () => { // 在渲染前修改ng-mocks托管的ActivatedRoute属性 beforeEach(() => MockInstance(ActivatedRoute, { snapshot: { params: { id: 2 } } })); it('should have an id of 2', () => { renderComponent(); expect(component.routeId).toEqual(2); }); }); });
方案2:直接修改自定义mock对象
如果需要保留自行定义的mock对象,利用引用类型的特性直接修改属性值即可,不需要用到MockInstance:
const mockActivatedRoute = { snapshot: { params: { id: 1 } } }; describe('MyComponent', () => { beforeEach(() => { return MockBuilder(MyComponent, MyModule) .provide({ provide: ActivatedRoute, useValue: mockActivatedRoute }) }); function renderComponent() { fixture = MockRender(MyComponent); component = fixture.point.componentInstance; } it('should have an id of 1', () => { renderComponent(); expect(component.routeId).toEqual(1); }); describe('when it inits with a different id', () => { // 渲染前直接修改mock对象的属性 beforeEach(() => { mockActivatedRoute.snapshot.params.id = 2; }); it('should have an id of 2', () => { renderComponent(); expect(component.routeId).toEqual(2); }); }); });
补充说明
不需要将routeId设为public直接修改,这类跳过依赖注入逻辑的测试无法验证组件从ActivatedRoute获取参数的逻辑正确性,没有实际测试价值。
内容的提问来源于stack exchange,提问作者iamsar
相关产品推荐
相关产品推荐

