用jest测试angular http服务



我想测试我的一个辅助函数是否在http服务层中被调用,但我得到了一个失败的测试。我是新手,所以请告诉我我做错了什么

服务层

public customerUpload(
file: Blob,
name?: string): Observable<CustomerResponse> {

if (name!== '') {
parameters = addQueryPara(name, 'name');
}
return this.http.post(file, parameters)
)

我想检查如果我用name调用CustomerUpload,它应该调用addQueryPara

My Spec file Test


import * as helper from 'app/shared/helper.ts';

describe('customerService', () => {
let service: customerService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule],
});
service = TestBed.inject(customerService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});

describe('when customer is called', () => {
beforeEach(() => {
const response = getMockResponse();
jest.spyOn(service, 'customerUpload').mockReturnValue(of(response) as any);
});
it('should add http params', () => {
service.customerUpload(new Blob(), 'learn');
expect(jest.spyOn(helper, 'addQueryPara')).toHaveBeenCalledTimes(1); // This is failing
});
});
});

addQueryPara失败。如何确保传递参数时,它会调用addQueryPara?

首先,您应该导入要测试的服务,以便稍后注入。在这种情况下,因为你需要模拟HttpClient,所以它不会发出任何真正的请求,你可以用TestBedHttpClientTestingModule来做(这里是jasmine的官方Angular文档,但它是相似的)。

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CustomerService } from './customer.service.ts'; // change this to the name of your route
describe('CustomerService', () => {
let service: CustomerService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [CustomerService] // <- Here we import the real service
});
service = TestBed.inject(CustomerService);
});
然后,在您的测试中,我看到您试图模拟HTTP POST请求。为此,你可以使用HttpTestingController,这是HttpClientTestingModule的一部分(在这里你有一个关于用Angular测试HTTP的很好的教程)。
describe("when customerUpload is called", () => {
const mockFile = // your mock
afterEach(() => {
// After every test, assert that there are no more pending requests.
httpTestingController.verify();
});
it("should invoke HTTP POST with the file", () => {
service.customerUpload(mockFile);
// Check for correct requests: should have made one request to POST search from expected URL
const req = httpTestingController.expectOne(customerUrl); // the url you expect to be called, including the queryParams, e.g.: customerUrl:4200?name=Mario
expect(req.request.method).toEqual("POST");
// Provide each http request with a mock response
req.flush(getMockResponse()); 
});
});

这是单元测试理论:如果addQueryPara函数没有导出到这个服务之外,你不应该显式地测试它。只需测试name !== ''

customerUpload

的结果是否如您所期望的那样工作另外,我不确定上传文件的实现,你应该看看这个评论。

我不知道jest,但我想当你做jest.spyOn(...).mockReturnValue(...)时,你正在存根方法并失去mockReturnValue的实现细节。

另一件事是,你是在调用方法之后监视,但你应该在调用方法之前监视。

我将首先使用HttpClientTestingModule而不是真正的HttpClientModule进行测试,因此实际的API调用不会发送,您可以断言发送了哪些API调用。

试着移除mockReturnValue,看看它是否通过。

import * as helper from 'app/shared/helper.ts';

describe('customerService', () => {
let service: customerService;
beforeEach(() => {
TestBed.configureTestingModule({
// !! Change to HttpClientTestingModule
imports: [HttpClientTestingModule],
});
service = TestBed.inject(customerService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});

describe('when customer is called', () => {
beforeEach(() => {
const response = getMockResponse();
!! remove mockReturnValue
jest.spyOn(service, 'customerUpload');
});
it('should add http params', () => {
// !! move this up before calling the method so we are actually spying before
const addSpy = jest.spyOn(helper, 'addQueryPara');
service.customerUpload(new Blob(), 'learn');
// !! assert now
expect(addSpy).toHaveBeenCalledTimes(1);
});
});
});

查看此链接以测试HTTP服务:https://testing-angular.com/testing-services/#testing-a-service-that-sends-http-requests

它使用了Karma和Jasmine而不是Jest,但是思想是一样的。

首先需要删除以下行:

jest.spyOn(service, 'customerUpload').mockReturnValue(of(response) as any);

正如AliF50所提到的,通过这样做,你完全模仿了service.customerUpload的内部行为,因此实际的实现将永远不会被调用,它将始终返回of(response)

此外,您可能希望将HttpClientModule的导入更改为HttpClientTestingModule,以便在您发出任何http请求(如this.http.post;

)时能够轻松地模拟和监视。这是你的代码看起来像(我假设addQueryPara是一个错别字,但没有改变它与您的示例一致):

import * as helper from 'app/shared/helper.ts';
import { customerService } from './customer-service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

describe('customerService', () => {
let service: customerService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});
service = TestBed.inject(customerService);
httpMock = TestBed.inject(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
describe('when customer is called', () => {
it('should add http params', () => {
// Given.
const mockFile = new Blob();
const mockName = 'learn';
const addQueryParaSpy = jest.spyOn(helper, 'addQueryPara');
// When.
service.customerUpload(mockFile, mockName);
// Then.
expect(addQueryParaSpy).toHaveBeenCalledWith(mockName, 'name');
});
});
});

相关内容

  • 没有找到相关文章

最新更新