Brian F爱
从专注于角图,Web技术以yobet英雄联盟及波特兰的Node.js的Google开发人员专家中学习。
广告 ·ultimatecourses.com.
用终极课程学习角度正确的方式

NGRX测试:减速器

了解如何使用Jest进行测试NGRX减速器。

目标是由于调度行动而将突变视为申请状态。️️

下载

在这篇文章中,我将使用演示申请。您可以克隆存储库或下载源代码的zip文件:

系列

此帖子是使用JEST测试NGRX的系列的一部分:

此应用程序的堆栈将是:

  • 角6
  • NGRX 6.
  • Jest和Angular-Jest-Preset模块
  • 茉莉花大理石模块
  • 创建假数据的煽动者

Jest Test Runner.

正如我上面提到的那样,这篇文章将使用Jest测试赛道。它比Karma更快(即使是无头铬),也可以使用茉莉花。事实上,如果您的大部分测试由CLI生成,那么您可以简单地为jest交换业力。

如果你是新人,用角度看看我的帖子

诺夫动作

首先,我们应该断言国家是突变为无效或诺沃行动减速器()功能在src / app / state / user / user.reducer.spec.ts

描述'未定义的行动'=>{'应该退回默认状态'=>{const行动={类型'诺普'}任何;const结果=减速器未定义行动;期望结果成为Initimstate.;};};

让我们查看上面的测试:

  • 在“应该返回默认状态”规范中,我们创建一个新的行动,谁的类型被设置为“noop”。
  • 然后我们援引减速器()功能指定未定义对于当前和诺普一起行动
  • 最后,我们期望结果状态与Initimstate.,这是默认值争论在减速器()功能。

如果我们运行我们的测试,它应该通过:

$NPM.测试

添加用户行动

在示例应用程序中,我为添加用户指定了一些操作SRC / app /州/用户/ user.actions.ts

出口枚举UserActiontypes.{添加用户='[用户]添加用户'addusersuccess.='[用户]添加用户成功'adduserfail.='[用户]添加用户失败'}

在里面src / app /用户/ containers / add / add.component.ts组成部分调度()添加用户行动。这将切换装载布尔属性在州,和添加用户效果src / app / store / user / user.effects.ts将举行援助userservice.adduser()方法,它将向我们的API发送一个请求以创建新的用户实体。请求完成后,我们会发出addusersuccess.行动,或者如果响应是错误(例如500个状态代码),我们会发出adduserfail.行动。

这是一个定义添加用户行动:

出口添加用户实施行动{readonly类型=UserActiontypes.添加用户;构造函数上市有效载荷{用户<用户>}{}}

为了有效载荷我们只是定义一个必须具有的对象用户财产,这是一个A.用户

接下来,让我们来看看减速器()执行此操作:

出口功能减速器=Initimstate.行动用户名{开关行动类型{案件UserActiontypes.添加用户返回{......装载真正错误未定义};}}

当。。。的时候添加用户派遣行动我们正在更新状态,以便装载布尔值设置为真正并确保了错误属性设置为未定义

这是测试添加用户行动在src / app / state / user / user.reducer.spec.ts文件:

描述'用户减速器'=>{描述'[用户]添加用户'=>{'应该切换加载状态'=>{const行动=添加用户{用户};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.错误未定义装载真正};};};};

让我们来查看测试:

  • 首先,我们的所有测试都在“用户减速器”测试套件内。
  • 在测试中,我们新起来添加用户操作,指定我们使用Faker创建的生成用户。
  • 然后我们援引减速器()功能,提供Initimstate.行动
  • 最后,我们期望结果等于一个新对象;首先传播Initimstate.对象,然后指定错误装载属性值。

addusersuccess.行动

接下来,让我们断言addusersuccess.操作返回新创建的新状态用户实体添加。

在此演示应用程序中,我正在使用@ ngrx /实体模块来管理集合用户对象。虽然可能没有必要断言单独使用实体适配器的状态突变,但我想明确测试每个操作,包括那些单独/主要使用适配器方法的操作(例如,附加())对于突变申请的状态。

一般来说,我认为这是安全的:

假设@ ngrx /实体适配器状态突变是经过战斗的,可能在您的应用程序中不需要测试

首先,这是一个定义addusersuccess.行动SRC / app /州/用户/ user.actions.ts

出口addusersuccess.实施行动{readonly类型=UserActiontypes.addusersuccess.;构造函数上市有效载荷{用户用户}{}}

而且,这里是案例陈述减速器()为了addusersuccess.返回新州的行动:

案件UserActiontypes.addusersuccess.案件UserActiontypes.LoadUserSuccess.{返回适配器adjone.行动有效载荷用户{......装载};}

正如你所看到的,我们调用附加()在实体适配器上的方法,提供创建(或加载)和切换的用户装载布尔属性到

现在,让我们看看测试中的测试src / app / state / user / user.reducer.spec.ts文件:

描述'[用户]添加用户成功'=>{'应该将用户添加到州'=>{const行动=addusersuccess.{用户};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.实体{[用户ID]用户}ids.[用户ID]装载};};};

在这个测试中,我们调用了减速器()功能,指定Initimstate.随着addusersuccess.我们创建了必要的有效载荷的行动。然后我们期望()结果等于Initimstate.额外的东西实体ids.通过适配器创建的属性附加()方法。

我们也断言了装载布尔属性已设置为。这实际上是在减速机中执行的唯一“手动”状态突变值得被测试。

adduserfail.行动

我们还应在添加新用户的HTTP请求失败时测试失败路径。为此,我们会宣传那个adduserfail.行动导致我们申请的新状态错误属性包含错误发生了。

首先,这是一个定义adduserfail.行动SRC / app /州/用户/ user.actions.ts

出口adduserfail.实施行动{readonly类型=UserActiontypes.adduserfail.;构造函数上市有效载荷{错误错误}{}}

而且,这里是案例陈述减速器()功能:

案件UserActiontypes.adduserfail.案件UserActiontypes.addusersfail.案件UserActiontypes.LoadUserFail.案件UserActiontypes.LoadUsersfail.案件UserActiontypes.updateUserfail.案件UserActiontypes.UpdateUsersfail.{返回{......错误行动有效载荷错误装载};}

您将注意到,在此应用程序中,当任何操作失败时,我们具有相同的结果:我们更新错误财产包含错误这是在行动中派出的有效载荷并切换装载布尔到

现在,让我们断言,该状态在适当的时候突变adduserfail.行动被派遣:

描述'[用户]添加用户失败'=>{'应该在状态下更新错误'=>{const错误=错误;const行动=adduserfail.{错误};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.错误装载};};};

这应该开始看起来很害怕。我们加入了adduserfail.行动,援引减速器()功能,并断言结果等于申请的预期状态。

LoadUser.LoadUserSuccess.LoadUserFail.

测试的测试LoadUser.LoadUserSuccess.LoadUserFail.几乎与添加用户的人数几乎没有专制。让我们快速看看每个人。

断言这一点LoadUser.行动结果等于预期的价值错误属性是未定义装载财产被切断到真正

描述'[用户]加载用户'=>{'应该切换加载状态'=>{const行动=LoadUser.{ID用户ID};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.错误未定义装载真正};};};

断言这一点LoadUserSuccess.行动结果等于预期的价值实体ids.属性包含在操作中发送的用户有效载荷

描述'[用户]加载用户成功'=>{'应该将用户加载到州'=>{const行动=LoadUserSuccess.{用户};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.实体{[用户ID]用户}ids.[用户ID]装载};};};

断言这一点LoadUserFail.行动结果等于预期的价值错误属性包含错误这是在行动中派出的有效载荷

描述'[用户]加载用户失败'=>{'应该在状态下更新错误'=>{const错误=错误;const行动=LoadUserFail.{错误};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.错误装载};};};

LoadUsers.LoadUsersSuccess.LoadUsersfail.

单位测试LoadUsers.LoadUsersSuccess.LoadUsersfail.行动是相似的,除了实体ids.属性已更新许多用户对象。

我们会跳过这一点LoadUsers.LoadUsersfail.为了简洁的测试,因为它们几乎与之相同LoadUser.LoadUserFail.测试。

让我们快点看看测试LoadUsersSuccess.行动:

描述'[用户]负载用户成功'=>{'应该将所有用户添加到州'=>{const用户=[用户];const行动=LoadUsersSuccess.{用户};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.实体用户降低entityMap.用户=>{......entityMap.[用户ID]用户}{}ids.用户地图用户=>用户ID装载};};};

在里面期望()断言我们使用array.prototype.reduce()创建的方法实体字典的用户对象。

@ ngrx / Entity库使用以下签名来存储实体在状态以便快速检索对象:

出口声明键入diblditnnum.<T.>={[ID]T.;};出口摘要字典<T.>实施intermennum.<T.>{[ID]T.;}

唯一标识符是一个或者,唯一标识符是属性名称(或密钥)实体目的。

这就是我们使用的原因降低()创建的方法实体匹配的对象intermennum.要么字典类型。

ids.数组只是一个数组ID价值观。我们使用地图()映射值的方法用户数组用户对象。

UpdateUserSuccess.

测试的测试更新用户updateUserfail.行动也与我们查看的现有测试相同,我们正在调度切换的动作装载财产并更新错误属性。

另一方面,接通一个断言的测试UpdateUserSuccess.动作突变我们的应用程序的状态有点复杂,并且坦率地说,有点冗长:

描述'用户减速器'=>{const用户用户={ID1名字'Anakin''天空步行者'};描述'[用户]更新用户成功'=>{'应该在州更新用户'=>{constUpdatedUser.用户={......用户名字'Darth''vader'};const行动=UpdateUserSuccess.{更新{ID用户ID变化UpdatedUser.}};const=减速器Initimstate.addusersuccess.{用户};期望toequal.{......Initimstate.实体{[用户ID]用户}ids.[用户ID]装载};const结果=减速器行动;期望结果toequal.{......实体{......实体[用户ID]UpdatedUser.}ids.[......ids.]装载};};};};

这是什么UpdateUserSuccess.测试在做:

  • 首先,我们定义一个UpdatedUser.使用当前的对象用户对象属性修改名字属性值。我们在这里去了一场星球大战主题。如果您反对星球大战,请与其一起进行此测试。如果你是一个粉丝,希望你能享受乐趣,我们将为我们的角度应用编写单元测试。
  • 然后我们新起来UpdateUserSuccess.行动与之更新属性。再次,我们正在使用@ ngrx /实体库,所以我们指定了一个更新类型签名ID变化属性。
  • 我们举行了减速器()提供的功能Initimstate.和一个新的addusersuccess.行动。
  • 我们断言那个addusersuccess.行动适当地返回一个新的添加新用户的对象。
  • 然后,我们调动减速器()再次函数。这次我们提供了那是一个结果addusersuccess.行动,以及行动实例UpdateUserSuccess.
  • 最后,我们断言了结果UpdateUserSuccess.行动代表了UpdatedUser.

UpdateUssSuccess.

测试的测试UpdateUssSuccess.行动类似于我们刚看过的测试UpdateUserSuccess.随着更新多个用户的添加:

描述'用户减速器'=>{const用户用户={ID1名字'Anakin''天空步行者'};描述'[用户]更新用户成功'=>{'应该将所有用户添加到州'=>{const参议员={ID2名字'sheev''Palpaatine'};constVader.={......用户名字'Darth''vader'};consts={......参议员名字'Darth'“周围”};const最初的用户=[用户参议员];const更新者=[Vader.s];const=减速器Initimstate.addUssssuccess.{用户最初的用户};const行动=UpdateUssSuccess.{更新[{ID用户ID变化Vader.}{ID参议员ID变化s}]};const结果=减速器行动;期望结果toequal.{......实体更新者降低entityMap.用户=>{......entityMap.[用户ID]用户}{}ids.更新者地图用户=>用户ID装载};};};};

我不会审查每行代码,但一般来说,我们要添加最初的用户到我们的应用程序,然后断言,通过该申请更新多个用户UpdateUssSuccess.行动导致预期的状态。

选择器

最后一次测试src / app / state / user / user.reducer.spec.ts是断言选择器操作更新选择用户我们的国家对象中的财产:

描述'[用户]选择用户'=>{'应该在状态下设置SelectsUlerId属性=>{const行动=选择器{ID用户ID};const结果=减速器Initimstate.行动;期望结果toequal.{......Initimstate.selectedUserid.用户ID};};};

运行测试

最后,我们使用测试:

$NPM.测试

我们应该看到我们所有的测试通过。

结论

写作单元测试能够玩得开心!☝️

没有真实地,可以轻松地完成使用NGRX的角度应用程序中的单元测试操作。这些例子中唯一有点繁琐写入写入的测试是更新测试,特别是一次更新多个实体。但是,我们现在具有优异的代码覆盖率☀️并确保我们的行动通过该行动适当地突变国家减速器()功能。

Brian F爱

嗨,我是布莱恩。我对类型名称,Angular和node.js感兴趣我嫁给了我最好的朋友邦妮,我住在波特兰和我滑雪(很多)。