Typescript 如何测试组件行为以响应承诺

Typescript 如何测试组件行为以响应承诺,typescript,jasmine,angular,es6-promise,Typescript,Jasmine,Angular,Es6 Promise,首先,我不认为它是重复的,因为SO问题和答案描述了angular1中承诺处理的测试,并通过调用$timeout.flush()或$rootScope.$apply()解决,因此不适用于此Angular2案例 我的问题是如何测试Angular2组件的逻辑,该组件在解决承诺后执行。(最好是茉莉花) 为了说明这一点,我修改了Angular2文档中的快速入门示例。Simple component列出现有的Hero,并允许注册新的Hero。heros列表和注册由一个服务完成,该服务以承诺的形式返回响应(带

首先,我不认为它是重复的,因为SO问题和答案描述了angular1中承诺处理的测试,并通过调用
$timeout.flush()
$rootScope.$apply()
解决,因此不适用于此Angular2案例

我的问题是如何测试Angular2组件的逻辑,该组件在解决承诺后执行。(最好是茉莉花)

为了说明这一点,我修改了Angular2文档中的快速入门示例。Simple component列出现有的Hero,并允许注册新的Hero。heros列表和注册由一个服务完成,该服务以承诺的形式返回响应(带有heros列表或新注册的hero对象)

现在,一旦注册了一个新的英雄(并解决了承诺),我希望组件选择英雄,并再次检索英雄列表:

...
register(heroName:string) {
  this.postRegistration(this._heroService.registerHero(heroName));
}
//this extra method helps testing without stubing of the service
postRegistration(heroPromise:Promise<Hero>) {
  heroPromise.then( hero => {
      //I want to test that the two actions below took place
      this.selectedHero = hero;
      this.getHeroes(); })
}

getHeroes() {
this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}
我将我的断言与传递给组件的承诺“挂钩”

我的第一个问题:我是幸运还是保证,如果我订阅了相同的承诺,并从其“then”子句jasmine done()调用,它将等待我的其他“订户”(在这种情况下是组件)处理该承诺和后续承诺

其次,是否有一种方法可以强制所有承诺在测试期间同步,从而解决整个问题

我发现了mock promise项目,它允许“发射”承诺,但它已经死了2年

这个问题应该足够普遍,可以有一个标准的答案

我是在Angular2Jasmine的背景下提问的,但是,我也对简单的“单元测试”方法感兴趣,例如,当前的测试完全独立于角度框架。请输入脚本,因为我通常不使用JS

整个代码(它是Angular2 Hero快速入门示例的简单克隆)如下所示:

我的第一个问题:

你应该始终确保回报承诺

register(heroName:string) {
  return this.postRegistration(this._heroService.registerHero(heroName));
}
//this extra method helps testing without stubing of the service
postRegistration(heroPromise:Promise<Hero>) {
  return heroPromise.then( hero => {
      //I want to test that the two actions below took place
      this.selectedHero = hero;
      return this.getHeroes(); })
}

getHeroes() {
  return this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}
寄存器(heroName:string){
返回this.postRegistration(this.\u heroService.registerHero(heroName));
}
//这个额外的方法有助于在不中断服务的情况下进行测试
注册后(承诺:承诺){
回报你的承诺。然后(英雄=>{
//我想测试以下两个动作是否发生
this.selectedHero=英雄;
返回此。getHeroes();})
}
getHeroes(){
返回此。_heroService.getheromes()。然后(heromes=>this.heromes=heromes);
}
这样,当您调用
时,异步部分被链接起来。然后(…)
返回值,否则异步调用将成为它们自己的断开连接的事件链,并且您无法获得有关它们何时执行或何时完成的任何信息

其次

有一个fakeAsync应该允许进行测试 (我自己还没试过)


否则,承诺是异步的,没有什么可以改变这一点。

@Gunter-answer让我走上了正确的道路,但由于他没有明确解决这个问题,我正在写我自己的答案

我的第一个问题

我真的只是幸运而已。对同一承诺做出后续呼吁,不会对之前的承诺产生任何影响。虽然这个测试通过了,但其他模式类似的测试失败了

从“business”方法返回承诺并链接到它,并不总是一个选项,因为它取决于方法逻辑,所以Gunter的建议并不总是可以遵循的

其次

Gunter提到Angular2 fakeAsync,它是测试承诺处理副作用的正确方法。尽管它是angular2测试库的一部分,但它可以以“单元测试”的方式使用,因为它不需要注入或其他角度依赖

使用它,调用
flushMicrotasks
inside
fakeAsync
body并测试副作用:

import {it,fakeAsync,tick,flushMicrotasks} from 'angular2/testing';
...
    it('correct side effect after processing promise',<any>fakeAsync(()  => {

        let p = Promise.resolve(X);

        //invoking business logic
        component.dealWithIt(p);

        flushMicrotasks();

        //now the side effects can be tested in synchronous way
        expect(component.selectedHero).toBe(hero);
        ...
    }));
从'angular2/testing'导入{it,fakeAsync,tick,flushMicrotasks};
...

信息技术(“处理承诺后正确的副作用”,我还找到了角度测试规范来证实这一点。

非常感谢您指出了伪异步,这是一种方式。我只是在没有接受的情况下对您的答案进行了投票。您没有解释如何处理承诺处理后副作用测试的主要问题。承诺链接可能并不总是可能的,这取决于测试中的方法是否能够返回承诺,这取决于方法逻辑。fakeAsync是一个头奖!但您没有解释它,所以我写了自己的答案。不用担心:)。我不知道
fakeAsync
。我没有使用打字脚本。我只使用Dart,我们有
Future
,而不是
Promise
,它们的工作原理基本相同。Dart中也有
fakeAsnyc
,但我从未使用过它。在Dart中使用
Future
比在TS中更容易一些。
import {it,fakeAsync,tick,flushMicrotasks} from 'angular2/testing';
...
    it('correct side effect after processing promise',<any>fakeAsync(()  => {

        let p = Promise.resolve(X);

        //invoking business logic
        component.dealWithIt(p);

        flushMicrotasks();

        //now the side effects can be tested in synchronous way
        expect(component.selectedHero).toBe(hero);
        ...
    }));