Brian F爱
从俄勒冈州波特兰的一位专注yobet英雄联盟于Angular、Web技术和Node.js的谷歌开发专家那里学习。
广告 ·ultimatecourses.com
以正确的方式学习Angular的终极课程

NGRX测试:效果

了解如何使用Jest进行测试NGRX效果。

下载

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

系列

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

此应用程序的堆栈将是:

  • 角6
  • NGRX 6.
  • Jest和angular- Jest -预置模块
  • 茉莉花大理石模块
  • 伪造数据的Faker

Jest测试运行器

正如我上面提到的,这篇文章将使用Jest测试运行器。它比Karma快得多(即使是在headless Chrome上),并且使用了类似jasmine的API。事实上,如果您的大多数测试都是由CLI生成的,那么您可以简单地将Karma替换为Jest。

如果你是新人,<一种href="//www.nxtmastery.com/2018/05/26/angular-jest-testing/">用角度看看我的帖子。

jasmine-marbles

我们将使用jasmine-marbles模块来模拟可观察对象。

以下有些链接有关NGRX有关大理石测试的更多信息:

总之,我们可以使用大理石图的字符串来随时间描述可观察的流。这使我们能够同步测试异步可观察流。

我们将使用两个主要功能:

  • 热()创造一个热的可观察流。
  • 冷()创造一个寒冷的可观察流。

我们将使用这些功能来断言我们申请中特定行动的结果导致我们描述的预期热或冷的可观察流。

大理石测试使用一个字符串来描述可观察流:

  • -dash表示虚拟时间传递的框架,这是10毫秒,但这并不是那么重要。
  • a-z0-9任何字母数字字符表示值。我们可以使用第二个论点热()冷()函数指定每个标记所代表的值。
  • ()将值组合在一起分为单帧。
  • ^胡萝卜表示冷可观察流中订阅的开始。
  • |管道表示完成通知。
  • 英镑符号(或哈希符号)表示错误通知。

设置

第一步是得到的测试用设置。我们将使用嘲笑功能jest.fn ()以及使用aTestActions类,以便可以修改可观察到的动作的来源。

示例中的所有代码都位于演示应用程序中src / app / / user / user.effects.spec.ts状态文件。

出口班级TestActions延伸行动{构造函数{超级空的;}来源可观察到的<任何>{来源=来源;}}出口函数尽量{返回TestActions;}描述“UserEffects”= >{行动TestActions;影响备用威胁;用户服务UserService;摘要= >{测试用configureTestingModule{供应商[备用威胁{提供行动useFactory尽量}{提供UserServiceumervalue.{addUser笑话FN.getUser笑话FN.住人笑话FN.更新用户笑话FN.}}]};行动=测试用得到行动;影响=测试用得到备用威胁;用户服务=测试用得到UserService;};“创建”= >{预计影响Tobeththy.;};};

我们来复习:

  • 首先,我们创造了TestActions类扩展行动类在@ngrx /影响。类添加一个mutator (setter)财产。
  • 我们还定义了getActions ()返回新实例的函数TestActions类。我们将把它作为工厂函数提供给Angular依赖注入测试用替补行动注入的课程备用威胁类。
  • 使用前提()方法,我们将测试用,提供了备用威胁在此示例中我们正在测试的类。我们也嘲笑了UserService使用jest.fn ()。这些只是占位符,我们将根据需要覆盖测试中。
  • 然后我们使用TestBed.get ()方法来存储对行动备用威胁UserService实例。
  • 最后,我们有标准的“应该被创建”测试,以确保我们的effects类被正确地实例化。

现在我们已经准备好开始为每种效果编写单元测试了src / app / / user / user.effects.ts状态

addUser影响

首先,让我们看看addUser我们将测试的效果:

出口班级备用威胁{@影响addUser可观察到的<行动>=美元的行为oftype.<AddUser>UserActiontypes.AddUser地图行动= >行动有效载荷jourtmap.有效载荷= >用户服务addUser有效载荷用户地图用户= >addusersuccess.{用户}CARTERROR.错误= >adduserfail.{错误};构造函数私人的美元的行为行动私人的用户服务UserService{}}

让我们迅速总结一下addUser影响:

  • 我们使用OFTYPE()方法筛选特定操作的所有操作AddUser行动。
  • 然后我们管道()可观察到几个运营商。
  • 首先,我们map ()可观察流数据返回有效载荷对象。
  • 其次,我们使用exhaustMap ()对象返回的可观察流addUser ()方法UserService (),指定用户有效载荷
  • 第三,我们map ()addusersuccess.使用所需的有效载荷对象提供的操作用户财产。
  • 最后我们使用了catchError ()操作符捕获异常,返回adduserfail.行动。
  • 然后调度从效果中产生的动作。

好的,让我们创建一个测试套件addUser影响:

描述'添加用户'= >{'应该与用户返回adduseruccess行动,同时成功'= >{const用户=generateUser.;const行动=AddUser{用户};const结果=addusersuccess.{用户};行动=热的“——”{一种行动};const响应=寒冷的'-a |'{一种用户};const预期的=寒冷的'--b'{B.结果};用户服务addUser=笑话FN.= >响应;预计影响addUsertobebservable.预期的;};'应该返回一个adduserfail动作,错误地失败'= >{const用户=generateUser.;const行动=AddUser{用户};const错误=错误;const结果=adduserfail.{错误};行动=热的“——”{一种行动};const响应=寒冷的”——# |”{}错误;const预期的=寒冷的“——(b |)”{B.结果};用户服务addUser=笑话FN.= >响应;预计影响addUsertobebservable.预期的;};};

我们的测试套件由两个测试组成。首先,我们断言成功路径;那个addusersuccess.由于效果而被派遣行动。其次,我们断言失败路径;那个adduserfail.由于其效果的异常而被调度行动。

让我们挖掘成功路径的细节:

  • 首先,我们调用generateUser()创造一个新的用户使用伪造者的对象。
  • 然后,我们新起来AddUser行动,指定有效载荷对象,并使用所需的用户财产。
  • 我们还新增了addusersuccess.行动。
  • 然后,我们设置内的财产TestActions类。回忆,行动测试用在我们嘲笑之后行动的依赖项备用威胁类。我们设置了到一个测试热观察对象,它在一个帧后发出下一个通知行动。这基本上将要断言的动作设置为行动在NGRX中可观察到的流。
  • 我们定义的响应常数作为寒冷可观察,在框架发出通知之后用户然后在第三帧发出一个完成通知。
  • 我们定义的预期的常数作为寒冷可观察,两名着名散发出来结果那就是addusersuccess.我们期待的行动。
  • 使用jest.fn ()Mock我们重写addUser方法的方法UserService返回响应
  • 最后,期望()那个addUser效应的结果是一个可观察的预期的热情可观察。

我们还测试了失败路径:

  • 首先我们使用generateUser.函数生成假用户对象。
  • 我们然后新起来AddUseradduserfail.行动。请注意,我们创建一个新的错误对象的冷可观察对象流创建时,保持引用以便使用响应
  • 我们设置了财产的行动的例子TestActions被注射的课程测试用
  • 请注意响应是一种寒冷可观察的,在框架之后,发出错误通知(磅标志)后跟完成通知(该|管道符号)。
  • 预期的Observable是一个冷Observable,在两帧之后,它会同时发出adduserfail.操作下一步通知和完成通知。注意时间是在下一个和完成通知之前的两个帧。这是因为我们模拟了之前的观测结果包括一个单独的框架和可观察对象响应流还包括在动作和错误的通知之前的单个时间帧。因此,它是经过两帧的虚拟时间预期的Observable会发出adduserfail.操作和完成通知。
  • 就像在以前的测试中一样,我们嘲笑addUser方法返回一个可观察对象响应
  • 最后,我们期望()那个addUser效果导致可观察到的符合预期的热情可观察。

LoadUsers.影响

在我们看测试之前LoadUsers.效果,让我们快速看看效果:

@影响LoadUsers.可观察到的<行动>=美元的行为oftype.<LoadUsers>UserActiontypes.LoadUsersjourtmap.= >用户服务住人地图用户= >LoadUsersSuccess.{用户}CARTERROR.错误= >LoadUsersfail.{错误};

当我们看这个效应时,有很多相似之处addUser的效果。一般来说,我们用UserService检索所有用户,然后映射到LoadUsersSuccess.行动。如果有什么东西,我们会派遣LoadUsersfail.行动。

这是测试套件,用于成功和失败路径LoadUsers.影响:

描述'loadusers'= >{'应该返回一个LoadUsersSuccess动作,与用户,在成功'= >{const用户=生成用户;const行动=LoadUsers;const结果=LoadUsersSuccess.{用户用户};行动=热的“——”{一种行动};const响应=寒冷的'-a |'{一种用户};const预期的=寒冷的'--b'{B.结果};用户服务住人=笑话FN.= >响应;预计影响LoadUsers.tobebservable.预期的;};'应该返回一个LoadUsersFail动作,并在失败时返回一个错误'= >{const行动=LoadUsers;const错误=错误;const结果=LoadUsersfail.{错误错误};行动=热的“——”{一种行动};const响应=寒冷的”——# |”{}错误;const预期的=寒冷的“——(b |)”{B.结果};用户服务住人=笑话FN.= >响应;预计影响LoadUsers.tobebservable.预期的;};};

这也应该与之前的成功和失败路径测试相似addUser的效果。主要差异是这些行动的不同行动和所需的有效载荷。此外,我们就像我们的那样写下两次测试addUser效果:一个是成功路径,另一个是失败路径。

loadUser测试套件也非常类似。为了简洁,我将跳过它,但请随意查看里面的测试src / app / / user / user.effects.spec.ts状态

更新用户影响

这是更新用户我们将测试的效果:

@影响更新用户可观察到的<行动>=美元的行为oftype.<UpdateUser>UserActiontypes.UpdateUser地图行动= >行动有效载荷jourtmap.有效载荷= >用户服务更新用户有效载荷用户地图用户= >UpdateUserSuccess.{更新{id用户id变化用户}}CARTERROR.错误= >UpdateUserFail{错误};

更新用户效果我们过滤特定的所有操作UpdateUser行动,然后使用exhaustMap ()对象返回的可观察对象UserService.updateUser ()实例方法。我们map ()成功的UpdateUserSuccess.从效果中发送的行动,或者我们catchError ()返回一个可观察对象的()UpdateUserFail行动。

的测试套件更新用户影响:

描述'更新用户'= >{'应该返回一个UpdateUserSuccess动作,与用户,在成功'= >{const用户=generateUser.;const行动=UpdateUser{用户};const结果=UpdateUserSuccess.{更新{id用户id变化用户}};行动=热的“——”{一种行动};const响应=寒冷的'-a |'{一种用户};const预期的=寒冷的'--b'{B.结果};用户服务更新用户=笑话FN.= >响应;预计影响更新用户tobebservable.预期的;};'应该返回updateUserFail动作,错误地返回错误'= >{const用户=generateUser.;const行动=UpdateUser{用户};const错误=错误;const结果=UpdateUserFail{错误};行动=热的“——”{一种行动};const响应=寒冷的”——# |”{}错误;const预期的=寒冷的“——(b |)”{B.结果};用户服务更新用户=笑话FN.= >响应;预计影响更新用户tobebservable.预期的;};};

我们测试成功和失败路径,建立必要的可观察到并断言所得到的可观察到是什么预期的

结论

使用jasmine-marbles模块,我们可以通过使用虚拟计时器(调度器)和嘲弄值和动作,轻松地使用同步代码测试异步效果。

Brian F爱

嗨,我是布莱恩。我对TypeScript, Angular和Node.js感兴趣。我和我最好的朋友邦妮结婚了,我住在波特兰,我经常滑雪。