首页 > 解决方案 > Angular 服务测试未通过

问题描述

我有一个使用 json-server 作为我的数据库的服务。我可以确认我的服务可以正常工作,因为我可以在组件中返回我的响应。但是我在尝试让 Jasmin 单元测试正常工作时遇到了这样的问题。

这是我的收据-数据-public.spec.ts 文件

import { ReceiptsDataPublic } from './receipts-data-public';
import { TestBed, fakeAsync, inject } from '@angular/core/testing';
import {
  HttpClientTestingModule,
  HttpTestingController,
} from '@angular/common/http/testing';
import { Receipt } from '../classes/receipt';
import { HttpClient } from '@angular/common/http';

describe('ReceiptsDataPublic', () => {
  let httpTestingController: HttpTestingController;
  let service: ReceiptsDataPublic;
  let httpClient: HttpClient;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [ReceiptsDataPublic],
      imports: [HttpClientTestingModule],
    });

    // We inject our service (which imports the HttpClient) and the Test Controller
    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
    service = TestBed.get(ReceiptsDataPublic);
  });

  beforeEach(() => {
    service = TestBed.get(ReceiptsDataPublic);
  });

  afterEach(() => {
    httpTestingController.verify();
  });

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

  it('should call getDevReceipts', () => {
    const serviceSpy = spyOn(service as ReceiptsDataPublic, 'getDevReceipts');
    service.getDevReceipts();
    expect(serviceSpy.calls.count()).toBe(1);
  });

  it('should call getReceipts', () => {
    const serviceSpy = spyOn(service as ReceiptsDataPublic, 'getReceipts');
    service.getReceipts();
    expect(serviceSpy.calls.count()).toBe(1);
  });

  it('returned Observable should match the right data', (done: DoneFn) => {
    const receipt = {
      id: 1,
      expenseDate: "2019-04-26T15:15:56.948Z",
      description: "Id cupiditate sint et dolores molestias consequuntur necessitatibus ipsa. Qui assumenda consequuntur enim cumque eos eligendi culpa sit aspernatur. Qui molestiae voluptate sed a mollitia voluptatem rerum. Neque accusamus voluptate iusto vero illo consequuntur. Et ut at quod tenetur veritatis recusandae quia sed. Perspiciatis ipsum consequuntur neque distinctio.",
      amount: 122.00,
      imgUrl:"https://source.unsplash.com/1600x900/?product"
    };

    service.getDevReceipts()
      .subscribe(res => {
        expect(res[0].amount).toEqual(12.9);
        done();
    });

    const req = httpTestingController.expectOne('http://localhost:3000/receipts');
    expect(req.request.method).toEqual('GET');
    req.flush(receipt);
  });
});

这是我的实际收据-数据-public.service.ts

import { Injectable } from '@angular/core';
import { ReceiptsDataService } from './receipts-data.service';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

import { Receipt } from '../classes/receipt';
import { throwError, Observable } from 'rxjs';

@Injectable()
export class ReceiptsDataPublic implements ReceiptsDataService {
  private LOCAL_REST_API_SERVER = 'http://localhost:3000/receipts';

  constructor(private httpClient: HttpClient) {}

  handleError(error: HttpErrorResponse) {
    let errorMessage = 'Unknown error!';
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      errorMessage = `Error: ${error.error.message}`;
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    return throwError('Something bad happened; please try again later.');
  }

  getDevReceipts(): Observable<Receipt[]> {
    return this.httpClient.get<Receipt[]>(this.LOCAL_REST_API_SERVER);
  }

  getReceipts(): Observable<Receipt[]> {
    throw new Error('Method not implemented.');
  }
}

但我不断得到以下信息:

业力测试失败

我不明白我在遵循 Angular 文档时做错了什么?如何设置我的服务测试以测试返回数据并将其与收据数据匹配?

当我更改为订阅函数而不是 toPromise() 时,我得到:

未捕获的类型错误:无法读取未定义抛出的属性“数量”

标签: angularionic-frameworkkarma-jasmineangular-services

解决方案


似乎您正在从模拟HttpClient而不是数组中刷新对象。

你应该做的只是改变

req.flush(receipt);

req.flush([receipt]);

您陷入的陷阱是服务的返回类型。请始终注意,类型仅用于开发目的,并且在运行时不存在。将您的返回类型标记为Observable<Receipt[]>并不能保证您在运行代码时会得到一个ObservableReceipt[]我假设您的代码运行完美,因为您的后端返回一个Receipt. 它在测试中的工作方式不同,因为您刷新了一个简单的对象而不是数组。在测试期间,req.flush成为您的后端服务。所以无论你输入什么req.flush,你的服务都会返回,即使它完全不是Receipt[]


推荐阅读