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.environmentNamethis.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();
  });
});