Angular Jest 旁观者在测试另一个服务时模拟服务依赖

时间:2021-06-28 21:53:56

标签: angular typescript unit-testing ts-jest angular-spectator

我正在使用,

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];

          }
        )
      );
  }


}

在构造函数中,它试图根据另一个自定义服务 (this.environmentName) 设置 2 个变量(this.environmentUrlruntimeConfig)。

我正在尝试使用以下内容进行测试:

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;
}

我如何模拟这些服务及其值,以便我可以让这个基本测试工作?

1 个答案:

答案 0 :(得分:0)

我会尝试使用来自观众的 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();
  });
});