单元测试可注入服务

Jir*_*vec 5 nomachine-nx karma-runner jestjs angular

我在 NX 工作区中执行简单的单元测试时遇到问题。我试图做的是 1) 配置 TestBed 和 2) 注入服务。但是,即使我使用脚手架虚拟服务,测试仍然失败,因为注入的服务据说是undefined

测试.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TestService {
  constructor() { }
}
Run Code Online (Sandbox Code Playgroud)

测试.服务.规格.ts

import { TestBed } from '@angular/core/testing';
import { TestService } from './test.service';

describe('TestService', () => {
  let service: TestService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [ TestService ]
    });
    service = TestBed.inject(TestService);
  });
  it('should be created', () => {
    expect(service).toBeTruthy();
  });
});
Run Code Online (Sandbox Code Playgroud)

有人知道为什么会发生这种情况吗?这里到底有什么问题呢?

编辑: 是的,我知道我可以创建一个模拟。然而,这个问题对我来说仍然很奇怪,所以我想弄清楚它的真相,而不是寻找解决方法。

编辑 2:直接 使用ng test <project> --test-file=<filename>会产生与使用 NXCLI 执行测试相同的结果

编辑 3:我按照要求在 StackBlitz 上分享了我的代码:https://stackblitz.com/edit/ng-unittest-issue

Rap*_*llo 7

undefined我在测试服务时遇到了完全相同的问题。这里解决我的问题有两件事:

  1. 如果您正在使用 Jest,请确保将其jest.mock('@angular/core/testing')从代码中删除。这是早期版本所必需的。
  2. 如果您的服务有任何其他注入,则必须将它们添加到 下的“providers”中TestBed.configureTestingModule

下面是一个简单 Http 服务的示例功能代码和单元测试,在 Angular 9 和 Angular 10 上进行了测试:

api.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ApiService {
  constructor(private http: HttpClient) {}
  baseUrl = 'https://my-api-url.com';

  //api/getId/:id
  getDataById(id: number): Observable<DataSample[]> {
    return this.http.get<DataSample[]>(`${this.baseUrl}/getId/${id}`);
  }
}

export interface DataSample {
  id: number;
  name: string;
}

Run Code Online (Sandbox Code Playgroud)

api.service.spec.ts

import {
  HttpClientTestingModule,
  HttpTestingController,
} from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { ApiService, DataSample } from './api.service';

describe('ApiService tests', () => {
  let service: ApiService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [ApiService],
    });
    service = TestBed.inject(ApiService);
    httpMock = TestBed.inject(HttpTestingController);
  });

  afterEach(() => httpMock.verify());

  it('should return an Observable<DataSample[]>', () => {
    expect(service).toBeTruthy();

    const id: number = 1;
    const mockResult: DataSample[] = [
      {
        id: 1,
        name: 'name1',
      },
      {
        id: 2,
        name: 'name2',
      },
    ];
    const expectedUrl = `https://my-api-url.com/getId/${id}`;

    service
      .getDataById(id)
      .subscribe((res) => expect(res).toBe(mockResult));

    const req = httpMock.expectOne(expectedUrl);
    expect(req.request.method).toBe('GET');
    req.flush(mockResult);
  });
});

Run Code Online (Sandbox Code Playgroud)

希望能帮助到你


top*_*oon 2

我认为获取服务实例是不正确的,因为您没有提供服务。

我曾经得到如下实例:

TestBed.configureTestingModule({
  providers: [TestService]
});
service = TestBed.inject(TestService);
Run Code Online (Sandbox Code Playgroud)