Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角度HTTP服务-测试失败_Angular_Angular Httpclient_Angular Test - Fatal编程技术网

Angular 角度HTTP服务-测试失败

Angular 角度HTTP服务-测试失败,angular,angular-httpclient,angular-test,Angular,Angular Httpclient,Angular Test,我正在学习Angular,并编写了一个服务,该服务仅使用Angular获取一些数据。我在编写验证服务成功获取数据的单元测试时遇到了很多困难。我已经发布了该服务的源代码和测试规范 示例.service.ts import { Injectable } from '@angular/core'; import {HttpClient} from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class Ex

我正在学习Angular,并编写了一个服务,该服务仅使用Angular获取一些数据。我在编写验证服务成功获取数据的单元测试时遇到了很多困难。我已经发布了该服务的源代码和测试规范

示例.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class ExampleService {

  constructor(private http: HttpClient) { }

  // get some sample data from an remote server
  getData() {
    return this.http.get('https://jsonplaceholder.typicode.com/todos/1');
  }
}
import { TestBed } from '@angular/core/testing';

import { ExampleService } from './example.service';
import {HttpClientTestingModule} from '@angular/common/http/testing';

describe('ExampleService', () => {
  let service: ExampleService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    service = TestBed.inject(ExampleService);
  });

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

  // this is the test that fails
  it('getData should return the correct value',
    (done: DoneFn) => {
      service.getData().subscribe(value => {
        console.log('test never reaches this line');
        // tslint:disable-next-line
        expect(value['userId']).toBe(1);
        done();
      });
    });
});

示例.service.spec.ts

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

@Injectable({
  providedIn: 'root'
})
export class ExampleService {

  constructor(private http: HttpClient) { }

  // get some sample data from an remote server
  getData() {
    return this.http.get('https://jsonplaceholder.typicode.com/todos/1');
  }
}
import { TestBed } from '@angular/core/testing';

import { ExampleService } from './example.service';
import {HttpClientTestingModule} from '@angular/common/http/testing';

describe('ExampleService', () => {
  let service: ExampleService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    service = TestBed.inject(ExampleService);
  });

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

  // this is the test that fails
  it('getData should return the correct value',
    (done: DoneFn) => {
      service.getData().subscribe(value => {
        console.log('test never reaches this line');
        // tslint:disable-next-line
        expect(value['userId']).toBe(1);
        done();
      });
    });
});


getData应返回正确的值
测试失败,错误为
错误:超时-异步函数未在5000ms内完成
。我注意到测试从未进入
subscribe()
方法。真正奇怪的是,当我在测试框架之外运行
getData()
时,它成功地将数据拉回来。我花了几个小时试图解决这个问题,并试图找到一个解决方案,但结果是空手而归。

当您对http请求进行单元测试时,您无法使用真正的服务并发出真正的http请求。因此,您必须模拟您的服务,创建伪服务和一个类似的getData()方法,该方法返回一个可观察的数据,与实际方法相同。您可以通过创建一个存根类并使用的RxJS来实现这一点,这是一个可观察的,可以由您的测试类使用

下面是一个如何做到这一点的例子

export class ExampleServiceStub {

  constructor() { }

  // get some sample data from an remote server
  getData() {
    return of(
        [
            {
                id: 1,
                name: 'Data name'
            }
        ]
    );
  }
}

在of()中,可以放置实际http请求将返回的数据。您必须像在测试类中注入真正的服务一样注入存根服务。

服务方法不一定需要使用
测试床进行单元测试。configureTestingModule
因为它们只是常规类。只有当您想在组件中测试它,或者想为您注入依赖项时,才需要它

因此,也可以在每个测试中手动实例化您的服务,并为其提供所需的依赖项。这也是测试管道和指令的默认方法

单元测试任何具有网络请求的内容,应模拟网络方法(或“单元”之外的任何内容)。在这种情况下,
httpClient
方法不在您的服务范围内,不应该对它们进行测试,因此它们会受到嘲笑

1)要模拟方法,请使用
jasmine.createSpyObj

let httpClient: { get: jasmine.Spy };
let service: ExampleService;
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);

beforeEach(() => {
  service = new ExampleService(<any> httpClientSpy);
});

http测试模块仅在您直接测试http服务时使用。如果目标是测试服务,您可以简单地模拟调用。尝试使用以下指南
it('should return "Yay!"', () => {
  const expectedResponse = "[{ hero: 'StackOverflow' }]";

  // return expectedResponse when anyone calls get
  httpClientSpy.get.and.returnValue(responseData(expectedResponse));

  service.getData().subscribe(response => {
    expect(service.heroes.length).toEqual(1)
  }, fail);
});