首页 > 解决方案 > 如何在没有测试平台的情况下模拟非类、非导出变量

问题描述

我有大量需要测试的服务。类测试,而不是组件测试,因此我不能使用 Testbed,但必须使用let service = new MyService. 但是,这些服务中有一小部分使用既不是类变量也不是导出的硬编码对象。

如何访问这些变量并使它们可用于构造函数?

我的.service.ts

import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ServicedItem } from '../../models/serviced-item.model';

const headers = new HttpHeaders() // <--- How to mock this???
.append('appended stuff here');

export class MyService {
  constructor(
    private readonly httpClient: HttpClient,
    @Inject('env') private env,
  ) {}

  public getServicedItem(id: string): Observable<ServicedItem> {
    return this.httpClient.get<ServicedItem>(
      `${this.env.webApiBaseUrl}servicedItem/${id}`, 
      { headers }
    );
  }
}

我的.service.spec.ts

import { HttpClientModule } from '@angular/common/http';
import { MyService } from './my.service';

jest.mock('@angular/common/http');

describe('MyService', () => {
  let service: MyService;
  const webApiBaseUrl: string = 'mocky-yeah'
  const env = { 'webApiBaseUrl': webApiBaseUrl } as any;
  const id: string = 'THE_id';
  const testPayload: string = 'Insert correct string here';

  describe('CLASS: mocked backend tests', () => {
    const httpClient: any = { get: jest.fn() };

    beforeEach(() => {
      service = new MyService(httpClient, env);
    });

    test('should be created', () => {
      expect(service).toBeTruthy();
    });

    describe('METHOD: getServicedItem', () => {
      test('should return servicedItem', (done) => {
        httpClient.get.mockImplementationOnce(() => of(testPayload));
        service.getServicedItem().subscribe((res) => {
          expect(httpClient.get).toBeCalledWith(`${webApiBaseUrl}servicedItem/${id}`);
          expect(res).toBe(testPayload);
          done();
        }, done.fail)
      });
    });

  });

照原样,我得到一个 TypeError: Cannot read property 'append' of undefined on the headers。我已经寻找方法来做到这一点......让我们说很久了。但是我发现的所有教程要么假设 Testbed,要么去上课或至少导出变量。但是必须有办法做到这一点,对吧?

并抛出错误:

● Test suite failed to run 
TypeError: Cannot read property 'append' of undefined 

4 | import { ServicedItem } from '../../models/serviced-item.model'; 
5 | > 
6 | const headers = new HttpHeaders() 
  |                  ^ 
7 | .append('Content-Type', 'application/json') 

编辑:

在一些输入后添加精确的错误块。

标签: angularunit-testingjestjs

解决方案


您遇到的问题是由

jest.mock('@angular/common/http');

在测试中。尝试将其删除,或正确模拟其导出。

import { HttpHeaders } from '@angular/common/http';
import { of } from 'rxjs';

import { MyService } from './my.service';

describe('MyService', () => {
  let service: MyService;
  const webApiBaseUrl = 'mocky-yeah';
  const env = {webApiBaseUrl} as any;
  const id = 'THE_id';
  const testPayload = 'Insert correct string here';

  describe('CLASS: mocked backend tests', () => {
    const httpClient: any = {get: jest.fn()};

    beforeEach(() => {
      service = new MyService(httpClient, env);
    });

    test('should be created', () => {
      expect(service).toBeTruthy();
    });

    describe('METHOD: getServicedItem', () => {
      test('should return servicedItem', async () => {
        httpClient.get.mockImplementationOnce(() => of(testPayload));
        const res = await service.getServicedItem(id).toPromise();
        expect(httpClient.get).toHaveBeenCalledWith(
          `${webApiBaseUrl}servicedItem/${id}`,
          {
            headers: jasmine.any(HttpHeaders),
          },
        );
        expect(res).toBe(testPayload);
      });
    });
  });
});
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Inject } from '@angular/core';
import { Observable } from 'rxjs';

const headers = new HttpHeaders() // <--- How to mock this???
  .append('Foo', 'Bar');

export class MyService {
  public constructor(
    private readonly httpClient: HttpClient,
    @Inject('env') private env,
  ) {}

  public getServicedItem(id: string): Observable<any> {
    return this.httpClient.get<any>(
      `${this.env.webApiBaseUrl}servicedItem/${id}`,
      { headers },
    );
  }
}

在此处输入图像描述


推荐阅读