【发布时间】:2019-04-21 13:02:28
【问题描述】:
我正在尝试测试我的 Angular 服务,该服务所做的部分工作是加载一个 JSON 文件,该文件用作服务的配置。我已经在测试中确认(通过console.log),我模拟 HTTP.get 调用以获取配置的方式正在工作并且正在返回模拟的配置对象:
// mocking the loading of the configuration in the beforeEach
authenticationService.loadInternalAuthModuleConfiguration();
const req = httpTestingController.expectOne('./internal-config.json');
req.flush({
redirectStorage: 'testing-redirect',
forbiddenStorage: 'testing-forbidden',
useAuthServerInDevelopment: true,
});
httpTestingController.verify();
当我在loadInternalAuthModuleConfiguration 函数中console.log 时,我看到上面显示的req.flush 中的对象和信息。在load 函数中,它获取该配置对象并将其值设置为服务中的私有变量:
loadInternalAuthModuleConfiguration() {
return this._http
.get(this.authConfig.internalAuthModuleConfigUrl)
.toPromise()
.then((configData: any) => {
this.internalConfigData = { ...configData };
this.internalConfigSubject.next(this.internalConfigData);
this.setPrivateClassVariables();
})
.catch((err: any) => {
this.internalConfigData = null;
this.internalConfigSubject.next(this.internalConfigData);
});
}
同样,console.log 表明在上面的 .then 方法中,configData 正确返回,并且它被设置为 this.internalConfigData。我的问题出现在下一步。
我想检查是否可以在设置 configData 对象后访问它。 (请记住,我在beforeEach 中运行了load 函数。)我在服务中有一个函数getInternalConfig 和getInternalConfigValueByKey,它将返回整个配置对象或指定键的值。当我在测试中运行它时,internalConfigData 对象和传入键的值未定义。
it('should be using testing-redirect as the redirectStorage', () => {
const configObj = authenticationService.getInternalConfig();
const redirectStorage = authenticationService.getInternalConfigValueByKey('redirectStorage');
expect(redirectStorage).toBe('testing-redirect');
});
该测试应该通过。如果我在load 函数中console.log internalConfigData 对象,我可以看到我给它的对象。我不确定为什么this.internalConfigData 似乎在beforeEach 和我的测试运行之间的某个地方丢失了数据。
为了确保此测试正确运行并通过,我在这里缺少什么?
编辑
这里也是TestBed.configureTestingModule 供参考:
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
AuthenticationService,
{ provide: AuthenticationConfig, useValue: mockAuthConfig },
{ provide: OidcConfigService, useValue: mockOidcConfigService },
{ provide: OidcSecurityService, useValue: mockOidcSecurityService },
{ provide: localStorage, useValue: mockLocalStorage },
],
});
编辑 2
这是整个beforeEach 和相关测试:
beforeEach(() => {
mockOidcConfigService = jasmine.createSpyObj(['load']);
mockOidcSecurityService = jasmine.createSpyObj(['getIsAuthorized']);
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
AuthenticationService,
{ provide: AuthenticationConfig, useValue: mockAuthConfig },
{ provide: OidcConfigService, useValue: mockOidcConfigService },
{ provide: OidcSecurityService, useValue: mockOidcSecurityService },
{ provide: localStorage, useValue: mockLocalStorage },
],
});
httpTestingController = TestBed.get(HttpTestingController);
authenticationService = TestBed.get(AuthenticationService);
store = {};
authenticationService.loadInternalAuthModuleConfiguration();
const req = httpTestingController.expectOne('./internal-config.json');
req.flush({
redirectStorage: 'testing-redirect',
forbiddenStorage: 'testing-forbidden',
useAuthServerInDevelopment: true,
});
httpTestingController.verify();
});
it('should be using testing-redirect as the redirectStorage', () => {
const configObj = authenticationService.getInternalConfig();
const redirectStorage = authenticationService.getInternalConfigValueByKey('redirectStorage');
expect(redirectStorage).toBe('testing-redirect');
});
【问题讨论】:
-
也许您有多个服务实例。其中只有一个获得模拟值。你的 providers 数组是什么样的?
-
@Isaac 我在问题的底部添加了
TestBed.configureTestingModule和 providers 数组。 -
首先我使用了测试平台,建议不要使用它。但既然你想问,我的下一个问题是你如何处理服务来向它提问?
-
@JosephEames 我添加了更多代码来说明这一点。我会说,除了 CLI 生成的测试文件中的内容之外,我没有出于任何特定原因使用
TestBed。如果有更好的方法,我愿意接受。 -
这是 CLI 的严重问题之一。测试文件默认使用测试平台。那是愚蠢的。所有 Angular 代码(模板之外)都是简单的 JS 类。你可以使用基本的 jasmine/karma 来测试它们。所以测试台的唯一需要是如果你想用一个组件来测试一个模板。
标签: angular unit-testing jasmine