为什么我不能单元测试方法`getGoods():Promise <good []>`(服务通过Http获取数据)?

时间:2017-05-28 22:03:53

标签: angular unit-testing http typescript asynchronous

我有一个名为GoodsDataService的服务。它通过Http服务获取一些数据。 Here is it

构造函数是:

constructor(private http: Http) {}

功能getGoods。它是通过Http服务获取数据,get方法:

  getGoods(): Promise<Good[]> {
    return this.http.get(this.goodsUrl)
      .toPromise()
      .then(response => response.json().data as Good[])
      .catch(this.handleError);
  }

注意toPromise方法。我是从this Angular official tutorial学到的。

现在关于getGoods方法的单元测试。以下是GoodsDataService的单元测试:hereThis is how I test this method

service.getGoods()
  .then(goods => {
    expect(goods.length).toEqual(10);
    expect(goods).toEqual([new Good()]);
  }); 

getGoods进行http调用,因此I have to mock it。这是代码:

const mockResponse = [
  {id: 11, name: 'Mr. Nice'},
  {id: 12, name: 'Narco'},
  {id: 13, name: 'Bombasto'},
  {id: 14, name: 'Celeritas'},
  {id: 15, name: 'Magneta'},
  {id: 16, name: 'RubberMan'},
  {id: 17, name: 'Dynama'},
  {id: 18, name: 'Dr IQ'},
  {id: 19, name: 'Magma'},
  {id: 20, name: 'Tornado'}
];

mockBackend.connections.subscribe((connection) => {
  connection.mockRespond(new Response(new ResponseOptions({
    body: JSON.stringify({data: mockResponse})
  })));
});

结果我有绿色测试。但由于这一点,他们不能成为绿色:expect(goods).toEqual([new Good()]);。结果必须为红色。无论如何,即使我把调试器放在then成功函数中(我预期的两个位置)IDE将在断点处停止,我会得到这个错误:

  

错误:未捕获(在承诺中):TypeError:无法读取属性&#39; length&#39;未定义的

所以,尽管我用一些数据模拟真实的http请求,但我在成功处理程序中得到undefined,我将其传递给then方法返回的承诺的getGoods

我的想法和研究

问题可能出在these lines

...
.then(response => response.json().data as Good[])
...

如果我将调试器放在那里,我每次都会看到response.json().dataundefined。顺便说一句,这段代码会触发两次(不是一次)。我认为这可以通过rxjs解释(http.get不仅会返回一次observable和subscription fire。如果我检查response.json()值是Promise。它被拒绝了。它中有一些错误堆栈跟踪。

enter image description here

就是这样:

TypeError: Already read
    at eval (eval at <anonymous> (http://localhost:9876/base/src/test.ts:56782:13), <anonymous>:1:10)
    at http://localhost:9876/base/src/test.ts:56782:13
    at ZoneDelegate.invoke (http://localhost:9876/base/src/polyfills.ts:1546:26)
    at ProxyZoneSpec.Array.concat.ProxyZoneSpec.onInvoke (http://localhost:9876/base/src/test.ts:55337:39)
    at ZoneDelegate.invoke (http://localhost:9876/base/src/polyfills.ts:1545:32)
    at Zone.run (http://localhost:9876/base/src/polyfills.ts:1296:43)
    at http://localhost:9876/base/src/polyfills.ts:1972:57
    at ZoneDelegate.invokeTask (http://localhost:9876/base/src/polyfills.ts:1579:31)
    at ProxyZoneSpec.Array.concat.ProxyZoneSpec.onInvokeTask (http://localhost:9876/base/src/test.ts:55361:39)
    at ZoneDelegate.invokeTask (http://localhost:9876/base/src/polyfills.ts:1578:36)

这段代码是如何创建的?我从this off tutorialthis great article学习。问题可能出在这里:看起来文章作者使用另一种方式来获取数据(他只使用订阅,没有承诺)。可能就是为什么我的测试不起作用。

可能我的问题与What does this error mean — Uncaught TypeError: Already read?有关。但是如何处理呢?

请注意,如果我在其他组件中使用服务 - 一切都像魅力一样!例如这段代码:

ngOnInit() {
  this.goodsDataService.getGoods()
    .then((data) => {
      debugger;
    })
}

data中显示正确的数据(数组)。

问题:我做错了什么?

有什么想法吗?

0 个答案:

没有答案