如何测试响应承诺的组件行为
How to test component behaviour in response to promise
首先,我不认为它是重复的,因为 SO 问题和答案描述了 angular1 中承诺处理的测试,并通过调用 $timeout.flush()
或 $rootScope.$apply()
解决,因此不适用于此Angular2例.
我的问题是如何测试 Angular2 组件的逻辑,该组件在解析承诺 后正在执行。 (最好是茉莉花)。
为了说明它,我修改了 Angular2 文档中的快速入门示例。简单组件列出现有英雄并允许注册新英雄。英雄列表和注册由服务完成,returns 以 Promises 响应(带有英雄列表或新注册的英雄对象)。
现在,一旦注册了新英雄(并且 Promise 已解决),我希望组件能够选择英雄并再次检索英雄列表:
...
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);
}
我将注册分为两种方法,因此可以在不对服务进行存根的情况下进行测试
将 Jasmine 异步测试与 done()
结合使用,我可以轻松地测试服务行为,即。它 returns 正确的承诺。
但是如何测试组件调用 getHeros
来刷新其列表或正确设置所选英雄。
我设法使用规范测试设置变量:
it("postRegistration sets selectedHero as registered one",done =>{
let promise = service.registerHero("Bosek"); //Promise.resolve(hero);
component.postRegistration(promise);
promise.then( hero => {
expect(component.selectedHero).toBe(hero);
expect(component.heroes.indexOf(hero)).toBeGreaterThan(0);
done();
})
})
我 "hooked" 我对传递给组件的相同承诺的断言。
我的第一个问题:我是幸运还是它保证如果我订阅相同的承诺并从它的 'then' 子句调用 jasmine done() 它会等到我的其他 "subscribers"(在那种情况下是组件)处理承诺和后续承诺。
其次,有没有办法在测试期间强制所有Promise同步,这样就可以解决整个问题。
我找到了允许 "firing" 承诺的模拟承诺项目 https://github.com/charleshansen/mock-promises,但它已经死了 2 年了。
这个问题应该很普遍,应该有一个标准答案。
我在 Angular2 和 Jasmine 的上下文中提问,但是,我对简单的 'unit test' 方法也是如此,例如当前测试完全独立于 Angular 框架。请打字稿,因为我通常不使用 JS。
完整代码(它是 Angular2 Hero 快速入门示例的简单克隆)位于:https://github.com/tzielins/angular-start-project
My first question:
您应该始终确保return 承诺
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);
}
这样,当您在 return 值上调用 .then(...)
时,异步部分将被链接起来,否则异步调用将成为它们自己断开的事件链,并且您无法获得有关它们何时调用的任何信息执行或完成时。
Secondly
有一个 fakeAsync 应该允许用于测试 Angular2 testing with fakeAsync
(我自己没试过)
否则 promises 是异步的,没有什么可以改变它。
@Gunter 的回答让我走上了正轨,但由于他没有明确解决问题,我正在写自己的答案。
My first question
我确实只是幸运。对同一个承诺进行后续调用,对之前的调用没有任何影响。虽然这个测试通过了,但其他类似模式的测试失败了。
从 "bussiness" 方法返回承诺并链接到它并不总是一个选项,因为它取决于方法逻辑,因此 Gunter 的建议并不总是可以遵循。
Secondly
Gunter 提到了 Angular2 fakeAsync,这是测试 Promise 处理的副作用的正确方法。虽然它是 angular2 测试库的一部分,但它可以以 'a unit test' 的方式使用,因为它不需要注入或其他 angular 依赖项。
使用它,在 fakeAsync
体内调用 flushMicrotasks
并测试副作用:
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);
...
}));
tick()
对承诺有类似的影响。
即使是在业务方法中创建的新承诺也可以保证完成。我在这里问了这个问题: 我还发现 Angular 测试规范证实了这一点。
首先,我不认为它是重复的,因为 SO 问题和答案描述了 angular1 中承诺处理的测试,并通过调用 $timeout.flush()
或 $rootScope.$apply()
解决,因此不适用于此Angular2例.
我的问题是如何测试 Angular2 组件的逻辑,该组件在解析承诺 后正在执行。 (最好是茉莉花)。
为了说明它,我修改了 Angular2 文档中的快速入门示例。简单组件列出现有英雄并允许注册新英雄。英雄列表和注册由服务完成,returns 以 Promises 响应(带有英雄列表或新注册的英雄对象)。
现在,一旦注册了新英雄(并且 Promise 已解决),我希望组件能够选择英雄并再次检索英雄列表:
...
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);
}
我将注册分为两种方法,因此可以在不对服务进行存根的情况下进行测试
将 Jasmine 异步测试与 done()
结合使用,我可以轻松地测试服务行为,即。它 returns 正确的承诺。
但是如何测试组件调用 getHeros
来刷新其列表或正确设置所选英雄。
我设法使用规范测试设置变量:
it("postRegistration sets selectedHero as registered one",done =>{
let promise = service.registerHero("Bosek"); //Promise.resolve(hero);
component.postRegistration(promise);
promise.then( hero => {
expect(component.selectedHero).toBe(hero);
expect(component.heroes.indexOf(hero)).toBeGreaterThan(0);
done();
})
})
我 "hooked" 我对传递给组件的相同承诺的断言。
我的第一个问题:我是幸运还是它保证如果我订阅相同的承诺并从它的 'then' 子句调用 jasmine done() 它会等到我的其他 "subscribers"(在那种情况下是组件)处理承诺和后续承诺。
其次,有没有办法在测试期间强制所有Promise同步,这样就可以解决整个问题。
我找到了允许 "firing" 承诺的模拟承诺项目 https://github.com/charleshansen/mock-promises,但它已经死了 2 年了。
这个问题应该很普遍,应该有一个标准答案。
我在 Angular2 和 Jasmine 的上下文中提问,但是,我对简单的 'unit test' 方法也是如此,例如当前测试完全独立于 Angular 框架。请打字稿,因为我通常不使用 JS。
完整代码(它是 Angular2 Hero 快速入门示例的简单克隆)位于:https://github.com/tzielins/angular-start-project
My first question:
您应该始终确保return 承诺
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);
}
这样,当您在 return 值上调用 .then(...)
时,异步部分将被链接起来,否则异步调用将成为它们自己断开的事件链,并且您无法获得有关它们何时调用的任何信息执行或完成时。
Secondly
有一个 fakeAsync 应该允许用于测试 Angular2 testing with fakeAsync (我自己没试过)
否则 promises 是异步的,没有什么可以改变它。
@Gunter 的回答让我走上了正轨,但由于他没有明确解决问题,我正在写自己的答案。
My first question
我确实只是幸运。对同一个承诺进行后续调用,对之前的调用没有任何影响。虽然这个测试通过了,但其他类似模式的测试失败了。
从 "bussiness" 方法返回承诺并链接到它并不总是一个选项,因为它取决于方法逻辑,因此 Gunter 的建议并不总是可以遵循。
Secondly
Gunter 提到了 Angular2 fakeAsync,这是测试 Promise 处理的副作用的正确方法。虽然它是 angular2 测试库的一部分,但它可以以 'a unit test' 的方式使用,因为它不需要注入或其他 angular 依赖项。
使用它,在 fakeAsync
体内调用 flushMicrotasks
并测试副作用:
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);
...
}));
tick()
对承诺有类似的影响。
即使是在业务方法中创建的新承诺也可以保证完成。我在这里问了这个问题: