Angular 在测试另一个服务时开玩笑旁观者模拟服务依赖性
Angular jest spectator mock service dependency while testing another service
我正在使用,
Angular CLI:10.2.3
节点:12.22.1
项目已构建,运行很好。我正在尝试使用 Jest 和 Spectator 添加测试。我有以下服务;我正在尝试 运行 一个非常基本的测试(可以模拟大部分值)。
@Injectable({
providedIn: 'root'
})
export class BasicAuthService {
environmentName = '';
environmentUrl = '';
constructor(
private http: HttpClient,
private config: ConfigService, //custom service 1
private runtimeConfig: RuntimeConfigService, // custom service 2
) {
this.environmentName = runtimeConfig.config.environmentName;
this.environmentUrl = this.environmentName == "localhost"
? "http://" + runtimeConfig.config.serviceUrl
: runtimeConfig.config.serviceUrl;
}
getAuthentication(credentials) {
let basicAuthHeaderString = 'Basic '
+ window.btoa(credentials.username + ':' + credentials.password);
let headers = new HttpHeaders({'Content-Type': 'application/json'});
let options = {
headers: headers
}
let envUrl = `${this.environmentUrl}/api/login`
return this.http.post<any>(envUrl, JSON.stringify(credentials), options)
.pipe(
map(
data => {
sessionStorage.setItem('authenticatedUser', credentials.username);
sessionStorage.setItem('token', data.token);
this.config.userGroupData = data.entitlements[0];
}
)
);
}
}
在构造函数中,它试图根据另一个自定义服务 (runtimeConfig
) 设置 2 个变量 (this.environmentName
和 this.environmentUrl
)。
我正在尝试使用以下方法进行测试:
describe('BasicAuthService', () => {
let spectator: SpectatorService<BasicAuthService>;
const createService = createServiceFactory({
service: BasicAuthService,
providers: [],
imports: [
HttpClientTestingModule],
entryComponents: [],
mocks: [ConfigService, RuntimeConfigService]
});
beforeEach(() => spectator = createService());
it('should be logged in', () => {
const runtimeConfigService = spectator.inject<RuntimeConfigService>(RuntimeConfigService);
const configService = spectator.inject<ConfigService>(ConfigService);
runtimeConfigService.config = {
environmentName: "localhost",
serviceUrl : "localhost:8071"
}; // This also does not work, same error.
expect(spectator.service.getAuthentication(createService)).toBeTruthy();
});
});
失败并出现错误:
? BasicAuthService > should be logged in
TypeError: Cannot read property 'environmentName' of undefined
22 | private runtimeConfig: RuntimeConfigService,
23 | ) {
> 24 | this.environmentName = runtimeConfig.config.environmentName;
| ^
运行时间配置如下。我尝试初始化值但没有帮助。
// RuntimeConfigService
@Injectable({
providedIn: 'root'
})
export class RuntimeConfigService {
config: Config;
constructor(private http: HttpClient) {}
loadConfig() {
return this.http
.get<Config>('./assets/runtime-config.json')
.toPromise()
.then(config => {
this.config = config;
});
}
}
export class Config {
serviceUrl: string;
environmentName: string;
}
如何模拟这些服务及其值,以便让这个基本测试正常运行?
我会尝试使用旁观者的 mockProvider
功能。您可以通过这种方式轻松地使用默认值模拟服务。当构造函数中的代码依赖于 DI 中的某些值时,它会派上用场。
import { mockProvider, ... } from '@ngneat/spectator/jest';
describe('BasicAuthService', () => {
let spectator: SpectatorService<BasicAuthService>;
const createService = createServiceFactory({
service: BasicAuthService,
providers: [
mockProvider(ConfigService, {
someFunction: () => someReturnValue; //if needed
}),
mockProvider(RuntimeConfigService, {
config: {
environmentName: "localhost",
serviceUrl : "localhost:8071"
}
})
],
imports: [HttpClientTestingModule],
entryComponents: [],
});
beforeEach(() => spectator = createService());
it('should be logged in', () => {
expect(spectator.service.getAuthentication(createService)).toBeTruthy();
});
});
我正在使用,
Angular CLI:10.2.3
节点:12.22.1
项目已构建,运行很好。我正在尝试使用 Jest 和 Spectator 添加测试。我有以下服务;我正在尝试 运行 一个非常基本的测试(可以模拟大部分值)。
@Injectable({
providedIn: 'root'
})
export class BasicAuthService {
environmentName = '';
environmentUrl = '';
constructor(
private http: HttpClient,
private config: ConfigService, //custom service 1
private runtimeConfig: RuntimeConfigService, // custom service 2
) {
this.environmentName = runtimeConfig.config.environmentName;
this.environmentUrl = this.environmentName == "localhost"
? "http://" + runtimeConfig.config.serviceUrl
: runtimeConfig.config.serviceUrl;
}
getAuthentication(credentials) {
let basicAuthHeaderString = 'Basic '
+ window.btoa(credentials.username + ':' + credentials.password);
let headers = new HttpHeaders({'Content-Type': 'application/json'});
let options = {
headers: headers
}
let envUrl = `${this.environmentUrl}/api/login`
return this.http.post<any>(envUrl, JSON.stringify(credentials), options)
.pipe(
map(
data => {
sessionStorage.setItem('authenticatedUser', credentials.username);
sessionStorage.setItem('token', data.token);
this.config.userGroupData = data.entitlements[0];
}
)
);
}
}
在构造函数中,它试图根据另一个自定义服务 (runtimeConfig
) 设置 2 个变量 (this.environmentName
和 this.environmentUrl
)。
我正在尝试使用以下方法进行测试:
describe('BasicAuthService', () => {
let spectator: SpectatorService<BasicAuthService>;
const createService = createServiceFactory({
service: BasicAuthService,
providers: [],
imports: [
HttpClientTestingModule],
entryComponents: [],
mocks: [ConfigService, RuntimeConfigService]
});
beforeEach(() => spectator = createService());
it('should be logged in', () => {
const runtimeConfigService = spectator.inject<RuntimeConfigService>(RuntimeConfigService);
const configService = spectator.inject<ConfigService>(ConfigService);
runtimeConfigService.config = {
environmentName: "localhost",
serviceUrl : "localhost:8071"
}; // This also does not work, same error.
expect(spectator.service.getAuthentication(createService)).toBeTruthy();
});
});
失败并出现错误:
? BasicAuthService > should be logged in
TypeError: Cannot read property 'environmentName' of undefined
22 | private runtimeConfig: RuntimeConfigService,
23 | ) {
> 24 | this.environmentName = runtimeConfig.config.environmentName;
| ^
运行时间配置如下。我尝试初始化值但没有帮助。
// RuntimeConfigService
@Injectable({
providedIn: 'root'
})
export class RuntimeConfigService {
config: Config;
constructor(private http: HttpClient) {}
loadConfig() {
return this.http
.get<Config>('./assets/runtime-config.json')
.toPromise()
.then(config => {
this.config = config;
});
}
}
export class Config {
serviceUrl: string;
environmentName: string;
}
如何模拟这些服务及其值,以便让这个基本测试正常运行?
我会尝试使用旁观者的 mockProvider
功能。您可以通过这种方式轻松地使用默认值模拟服务。当构造函数中的代码依赖于 DI 中的某些值时,它会派上用场。
import { mockProvider, ... } from '@ngneat/spectator/jest';
describe('BasicAuthService', () => {
let spectator: SpectatorService<BasicAuthService>;
const createService = createServiceFactory({
service: BasicAuthService,
providers: [
mockProvider(ConfigService, {
someFunction: () => someReturnValue; //if needed
}),
mockProvider(RuntimeConfigService, {
config: {
environmentName: "localhost",
serviceUrl : "localhost:8071"
}
})
],
imports: [HttpClientTestingModule],
entryComponents: [],
});
beforeEach(() => spectator = createService());
it('should be logged in', () => {
expect(spectator.service.getAuthentication(createService)).toBeTruthy();
});
});