【问题标题】:How to Test Angular2 / TypeScript HTTPService without Mock如何在没有 Mock 的情况下测试 Angular2 / TypeScript HTTPService
【发布时间】:2016-06-28 12:08:28
【问题描述】:
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';

@Injectable()
export class HttpService {
  result: any;

  constructor(private http:Http) {
  }

   public postRequest(){
       return this.http.get('http://httpbin.org/get');    
  }
}

上面是我的代码,这是我的测试:

不想模拟任何东西,只是测试真正的 http 连接。

编辑 - 新的 service.spec 文件:

import {beforeEachProviders, beforeEach, it, describe, expect, inject} from '@angular/core/testing';
import {HttpService} from '../../providers/http-service/http-service';
import {TranslateService} from 'ng2-translate/ng2-translate';
import {Goal} from '../../providers/goal/goal';
import {NavController} from 'ionic-angular';
import {HTTP_PROVIDERS, Http} from '@angular/http';

describe('Http Service Test', () => {

      beforeEachProviders(() => {
        return [
            HTTP_PROVIDERS,
            HttpService
        ];
    });

    it('should return response when subscribed to postRequest',
        inject([HttpService], (httpService: HttpService) => {

            httpService.postRequest().subscribe((res) => {
                expect(res.text()).toBe('hello raja');
            }); 
    }));
});

这些是我在业力控制台中的错误:

28 06 2016 14:33:32.067:ERROR [Chrome 51.0.2704 (Mac OS X 10.11.4) | Http Service Test | should return response when subscribed to postRequest]: TypeError: Cannot read property 'getCookie' of null
    at CookieXSRFStrategy.configureRequest (http://localhost:9876/absolute/var/folders/vy/18sb1wqs60g734bhr75cw9_r0000gn/T/9b9439f5f9c1590d3052594bcae9e877.browserify?26719cf22e6406ebc638b6b187c777666dcc5698:36568:81)
    at XHRBackend.createConnection (http://localhost:9876/absolute/var/folders/vy/18sb1wqs60g734bhr75cw9_r0000gn/T/9b9439f5f9c1590d3052594bcae9e877.browserify?26719cf22e6406ebc638b6b187c777666dcc5698:36583:28)
    at httpRequest (http://localhost:9876/absolute/var/folders/vy/18sb1wqs60g734bhr75cw9_r0000gn/T/9b9439f5f9c1590d3052594bcae9e877.browserify?26719cf22e6406ebc638b6b187c777666dcc5698:37476:20)

【问题讨论】:

  • 如果您的测试超出了类的边界并且到达其他外部服务不是单元测试,那么您可能需要集成测试。
  • 通过单元测试框架构建集成测试是合法的。请评论者提供答案,而不是与单元测试和模拟相撞。

标签: testing typescript angular integration-testing


【解决方案1】:

您首先需要为模拟 HTTP 后端配置提供程序:

describe('HttpService Tests', () => {
  beforeEachProviders(() => {
    return [
      HTTP_PROVIDERS,
      provide(XHRBackend, { useClass: MockBackend }),
      HttpService
   ];
});

那么你就可以这样使用mock后端了:

mockBackend.connections.subscribe(
  (connection: MockConnection) => {
    if (connection.request.url === 'file1.json') {
      // Simulate an error
      var err = new ResponseError();
      err.status = 404;
      connection.mockError(<Error>err);
    } else {
      // Simulate a successful response
      connection.mockRespond(new Response(
        new ResponseOptions({
          body: ['i love angular2']
        })));
    }
  });

httpService.postRequest().subscribe((res:Respsone) => {
  expect(res.text()).toBe('hello raja');
});

编辑

如果您想使用真实连接进行测试,请仅使用经典的 HTTP_PROVIDERS:

describe('HttpService Tests', () => {
  beforeEachProviders(() => {
    return [
      HTTP_PROVIDERS,
      HttpService
   ];
});

编辑1

由于你的调用是异步的,你可以使用async:

it('should return response when subscribed to postRequest',
    async(inject([HttpService], (httpService: HttpService) => {

        httpService.postRequest().subscribe((res) => {
            expect(res.text()).toBe('hello raja');
        }); 
})));

【讨论】:

  • 好的,我用您回复中的新代码更新了我的问题。你能确认它有效吗? (我仍然在业力中遇到捆绑错误)
  • 您使用哪个版本的 Angular2?也许你可以使用async...我相应地更新了我的答案
  • 最新版本的 angular2.(RC1 2.0.0) 非常感谢您的帮助!我现在将测试您的建议。另见stackoverflow.com/questions/34987391/…
  • 好的,我发布的链接,测试现在通过了,但我的“res”/结果是空的。有任何想法吗? RC3 运气好吗?
  • 我会调试你的测试。我的意思是在不将singleRun 选项设置为true 的情况下启动业力,然后单击浏览器中的调试按钮。然后你可以在 service 和 test 中添加断点来查看 HTTP 请求...
【解决方案2】:

https://angular.io/docs/ts/latest/api/http/testing/MockBackend-class.html

import {BaseRequestOptions, Http} from '@angular/http';
import {MockBackend} from '@angular/http/testing';
it('should get some data', inject([AsyncTestCompleter], (async) => {
  var connection;
  var injector = Injector.resolveAndCreate([
    MockBackend,
    {provide: Http, useFactory: (backend, options) => {
      return new Http(backend, options);
    }, deps: [MockBackend, BaseRequestOptions]}]);
  var http = injector.get(Http);
  var backend = injector.get(MockBackend);
  //Assign any newly-created connection to local variable
  backend.connections.subscribe(c => connection = c);
  http.request('data.json').subscribe((res) => {
    expect(res.text()).toBe('awesome');
    async.done();
  });
  connection.mockRespond(new Response('awesome'));
}));

https://angular.io/docs/ts/latest/api/http/testing/MockConnection-class.html

var connection;
backend.connections.subscribe(c => connection = c);
http.request('data.json').subscribe(res => console.log(res.text()));
connection.mockRespond(new Response(new ResponseOptions({ body: 'fake response' }))); //logs
'fake response'

【讨论】:

  • 不,不,我明显不想嘲笑... ;D
  • 那有什么问题呢?如果你不模拟Http,那么它不是单元测试而是集成测试。
  • 我的代码有一些基本的 TypeScript / Angular2 误解。我不知道是哪个。我可以帮你搞定。
猜你喜欢
  • 1970-01-01
  • 2011-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
相关资源
最近更新 更多