Angular 使用 mockedService 进行测试不会 return 模拟数据
Angular Test with mockedService doesn't return the mocked Data
显然,我仍然缺少理解模拟服务的重要内容,我很乐意提供一些信息。
我想在我的组件中测试的代码是:
modulesToDisplay: any[] = [];
...
getModules() {
this.configService.getModulesToDisplay().subscribe(modules => {
this.modulesToDisplay = modules;
}
);
}
我想测试当我从服务中获取内容时是否重新分配了 modulesToDisplay。所以在我的测试文件中,我创建了一个 serviceMock,其中 returns 一个包含两个项目的数组
let configServiceMock: any;
...
beforeEach(async(() => {
configServiceMock = jasmine.createSpyObj('ConfigService', ['getModulesToDisplay']);
configServiceMock.getModulesToDisplay.and.returnValue( of(['firstmodule', 'secondmodule']) );
...
providers: [
{ ConfigService, useValue: configServiceMock }
]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should assign result to modulesToDisplay', () => {
component.getModules();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
});
...
我预计这个测试会通过,因为我认为在我的测试中调用 'component.getModules();' 会使用模拟数据。但它没有, modulesToDisplay
仍然是我在组件中初始化的空数组。所以我想我还是没有理解mocking数据的正确原理。
即使 of
应该发出你的模拟值,我怀疑你可能仍然需要在异步上下文中执行它。如果您将规格更改为:
会发生什么
it('should assign result to modulesToDisplay', fakeAsync(() => {
component.getModules();
flushMicrotasks();
fixture.detectChanges();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
}));
通常当我的模拟似乎没有被使用时,这与我提供给配置的模拟对象与提供给 TestBed.configureTestingModule 的对象不匹配有关。
我尝试过两种方法来解决这个问题。
1.) 不再使用 useValue
构建提供程序,而是像这样切换到 useFactory
:
...
providers: [{ provide: ConfigService, useFactory: () => configServiceMock }]
2.) 另一种方法是在配置后获取服务进行测试,如下所示:
const csMock = jasmine.createSpyObject('ConfigureService', [...]);
TestBed.configureTestingModule(
...
providers: [{ provide: ConfigureService, useValue: csMock }]
);
configServiceMock = TestBed.get(ConfigureService);
模拟非常简单。让我帮你:
beforeEach(async(() => {
...
providers: [
{ ConfigService, useClass: MockConfigService}
]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should assign result to modulesToDisplay', () => {
component.getModules();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
});
模拟class
export class MockConfigService{
getModulesToDisplay(){
return of({
// whatever module object structure is
})
}
}
这会很有效。我强烈建议您 this article which has a real world example to test a component. For the basics, this article would be helpful
显然,我仍然缺少理解模拟服务的重要内容,我很乐意提供一些信息。
我想在我的组件中测试的代码是:
modulesToDisplay: any[] = [];
...
getModules() {
this.configService.getModulesToDisplay().subscribe(modules => {
this.modulesToDisplay = modules;
}
);
}
我想测试当我从服务中获取内容时是否重新分配了 modulesToDisplay。所以在我的测试文件中,我创建了一个 serviceMock,其中 returns 一个包含两个项目的数组
let configServiceMock: any;
...
beforeEach(async(() => {
configServiceMock = jasmine.createSpyObj('ConfigService', ['getModulesToDisplay']);
configServiceMock.getModulesToDisplay.and.returnValue( of(['firstmodule', 'secondmodule']) );
...
providers: [
{ ConfigService, useValue: configServiceMock }
]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should assign result to modulesToDisplay', () => {
component.getModules();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
});
...
我预计这个测试会通过,因为我认为在我的测试中调用 'component.getModules();' 会使用模拟数据。但它没有, modulesToDisplay
仍然是我在组件中初始化的空数组。所以我想我还是没有理解mocking数据的正确原理。
即使 of
应该发出你的模拟值,我怀疑你可能仍然需要在异步上下文中执行它。如果您将规格更改为:
it('should assign result to modulesToDisplay', fakeAsync(() => {
component.getModules();
flushMicrotasks();
fixture.detectChanges();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
}));
通常当我的模拟似乎没有被使用时,这与我提供给配置的模拟对象与提供给 TestBed.configureTestingModule 的对象不匹配有关。
我尝试过两种方法来解决这个问题。
1.) 不再使用 useValue
构建提供程序,而是像这样切换到 useFactory
:
...
providers: [{ provide: ConfigService, useFactory: () => configServiceMock }]
2.) 另一种方法是在配置后获取服务进行测试,如下所示:
const csMock = jasmine.createSpyObject('ConfigureService', [...]);
TestBed.configureTestingModule(
...
providers: [{ provide: ConfigureService, useValue: csMock }]
);
configServiceMock = TestBed.get(ConfigureService);
模拟非常简单。让我帮你:
beforeEach(async(() => {
...
providers: [
{ ConfigService, useClass: MockConfigService}
]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should assign result to modulesToDisplay', () => {
component.getModules();
expect(component.modulesToDisplay.length).toBeGreaterThan(0);
});
模拟class
export class MockConfigService{
getModulesToDisplay(){
return of({
// whatever module object structure is
})
}
}
这会很有效。我强烈建议您 this article which has a real world example to test a component. For the basics, this article would be helpful