我在几周前开始使用ng-mock,因为我认为它是为这种情况设计的,但对于我的生活,我不知道如何实现它。
简而言之,在定义了MockBuilder/MockRender之后,可以在嵌套的描述/测试中更改模拟提供程序的值吗?
在我的应用程序中,我经常有依赖于根据上下文提供不同数据的服务的组件。在静态的情况下,测试起来很简单。我将在这里使用ActivatedRoute作为一个例子,因为它让我感到悲伤:
const mockActivatedRoute = { snapshot: { params: { id: 1 } };
describe('MyComponent', () => {
MockInstance.scope('all');
beforeEach(() => {
return MockBuilder(MyComponent, MyModule)
.provide({ provide: ActivatedRoute, useValue: mockActivatedRoute })
});
beforeEach(() => {
fixture = MockRender(MyComponent);
component = fixture.point.componentInstance;
});
// Imagine the component has a routeId provided by the ActivatedRoute
it('should have an id of 1', () => { expect(component.routeId).toEqual(1); });
});
一切顺利。
但是在这个测试之后,我想运行另一个套件来修改服务;假设id
现在等于2。我假设这是MockInstance
的角色:能够为给定的测试动态地更改所提供的服务等。
describe
:
describe('MyComponent', () => {
...
describe('when it inits with a different id', () => {
MockInstance.scope();
beforeEach(MockInstance(mockActivatedRoute, () => {
snapshot: { params: { id: 2 } }
}));
it('should have an id of 2', () => { expect(component.routeId).toEqual(2); });
});
});
这个测试将失败,因为新的模拟值从未实现,并且routeId
保持不变。
我知道这是一个不好的例子。我使用MockInstance.remember
或尝试初始化服务实例本身,以多种不同的方式重写了这些测试,但都没有成功。据我所知,MockBuilder和MockInstance似乎不应该一起使用,而且在ng-mocks站点上也没有这样的示例。似乎唯一的方法来构建测试的情况下,像这样的是构建单独的describes
与他们自己的MockBuilder和MockRender。
或者我最好的选择是让routeId
公开并直接操纵它?
MockBuilder
可以与MockInstance
一起使用。需要注意的是,MockInstance
适用于尚未初始化的服务。换句话说,它在MockRender
或TestBed.createComponent
之前生效。
一旦调用了它们中的任何一个,您应该通过TestBed.inject
获得实例并直接模拟它们,例如,使用ngMocks.stub
和ngMocks.stubMember
。
const service = TestBed.inject(Service);
let value: any;
ngMocks.stubMember(service, 'name', v => (value = v), 'set');
// value === undefined
service.name = 'fake';
// value === 'fake'
在您的第二次测试中,您想要更改ActivatedRoute
,因此您应该使用它而不是mockActivatedRoute
,此外,因为您在测试之间重用TestBed
,您应该依赖TestBed.inject
而不是MockInstance
:
beforeEach(() => {
const activatedRoute = TestBed.inject(ActivatedRoute);
ngMocks.stub(activatedRoute, {
snapshot: {
params: {
id: 2,
},
},
});
});