繁体   English   中英

角度,测试,依赖项注入,http.get……有助于了解

[英]Angular, test, dependency injection, http.get … Help to understand

首先对不起我的英语。

我正在使用Angular,并通过他的测试开发了一个简单的服务。

该服务使用http.get方法加载JSON文件,并将其内容存储在变量中。 目的并不重要。

下面的代码有效:

首先服务

import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
import {Constants} from 'config/constants';
import 'rxjs/Rx';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LoadJsonFileService {
  private config: Object = null;

  constructor(private http: Http) {
  }

  private loadJsonAndUpdateConfig() {
    this.http
      .get(Constants.CONFIG_FILE_NAME)
      .map(response => response.json())
      .catch((error: any): any => {
        return Observable.throw(error.json().error || 'Server error');
      }).subscribe((configJson) => {
        this.config = configJson;
      });
  }
  public getConfig(key: string): string {
    if (!this.config) {
      this.loadJsonAndUpdateConfig();
    }
    return this.config[key];
  }
}

然后测试:

import {BaseRequestOptions, ConnectionBackend, Http, RequestOptions, Response, ResponseOptions} from '@angular/http';
import {MockBackend, MockConnection} from '@angular/http/testing';
import {LoadJsonFileService} from './load-json-file.service';
import {inject, TestBed} from '@angular/core/testing';

describe('Test suite ...', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        {provide: RequestOptions, useClass: BaseRequestOptions},
        {provide: ConnectionBackend, useClass: MockBackend},
        Http,
        LoadJsonFileService
      ]
    });
  });

  it('The test ...', inject([ConnectionBackend, LoadJsonFileService],
    (backend,
     service: LoadJsonFileService) => {
      backend.connections.subscribe((c: MockConnection) => {
        c.mockRespond(new Response(new ResponseOptions({body: {key: 'foo'}})));
      });

      expect(service.getConfig('key')).toBe('foo');
    }));

});

测试还可以

该代码不起作用,我也不知道为什么:

import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
import {Constants} from 'config/constants';
import 'rxjs/Rx';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LoadJsonFileService {
  private config: Object = null;

  constructor(private http: Http) {
    this.loadJsonAndUpdateConfig();
  }

  private loadJsonAndUpdateConfig() {
    this.http
      .get(Constants.CONFIG_FILE_NAME)
      .map(response => response.json())
      .catch((error: any): any => {
        return Observable.throw(error.json().error || 'Server error');
      }).subscribe((configJson) => {
        this.config = configJson;
      });
  }
  public getConfig(key: string): string {
    return this.config[key];
  }
}

不同之处在于在构造函数中而不是在getConfig方法中调用this.loadJsonAndUpdateConfig()。 测试失败 :

TypeError: null is not an object (evaluating 'this.config[key]')

当我进行一些调试时,subscribe方法将永远不会触发,就像从未调用过http.get一样。

我很困惑,有人能解释我这种行为吗?

谢谢,

燕姿

长话短说,只需将默认值分配给变量

private config: Object = {};

长版本:第一个代码示例也不应该起作用,除非您在执行此this.config[key]片段之前向某处的config变量分配了某些内容或后端请求完成(竞争条件),但是如果该操作在本地(或在测试中),它可能在服务器上损坏。

基本上, getConfig() )在this.config = configJson;之前被调用(我在模板中假设) this.config = configJson; Http请求是“异步的”,即js / ts / angular不要等到它完成为止,随后在HTTP请求启动后立即执行后续代码。

如果要测试它,请在返回值之前添加异步超时,或者最好查看InMemoryWebApiModule角度文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM