by Marcelo Lotif

通过马塞洛·洛蒂夫(Marcelo Lotif)

使用React,Redux和Router进行真正的集成测试 (Real integration tests with React, Redux and Router)

After being bitten a couple of times by bad refactoring and a broken app — even with all my tests green — I started to research about integration tests in React. Possibly also with Redux and React Router.

在经历了糟糕的重构和坏掉的应用程序几次咬伤之后,即使我的所有测试都是绿色的,我也开始研究React中的集成测试。 可能还可以使用Redux和React Router。

To my absolute shock, I couldn’t find any good material out there. The ones I found either were doing incomplete integration tests or simply doing it the wrong way.

令我震惊的是,我找不到任何好的材料。 我发现这要么是在进行不完整的集成测试,要么就是以错误的方式进行。

So here we’re going to build an integration test that initializes a React component, fires a simulated user interaction and assert that our component changes the way we expect it to change.

因此,这里我们将构建一个集成测试,该测试将初始化一个React组件,触发一个模拟的用户交互,并断言我们的组件改变了我们期望它改变的方式。

What this is not about: unit testing. I’m not going to dive into this right now, but there is a very good reason we at Wave (we’re hiring, by the way!) are slowing down on our unit tests and switching to integration tests. Scroll to the bottom if you’re interested in that.

不是关于:单元测试。 我现在不打算深入探讨这个问题,但是有一个很好的理由说明我们Wave的速度 ( 我们正在招聘 ,顺便说一句!)正在减慢我们的单元测试并切换到集成测试。 如果对此感兴趣,请滚动到底部。

Disclosure: I wouldn’t have had those tests working as smoothly as they are now if it wasn’t for the great front end folks at Wave, especially the amazing Tommy Li who figured out how to connect the router, so thank you!

披露:如果不是Wave的优秀前端人员,尤其是那些想出如何连接路由器的惊人的Tommy Li ,那我将没有那些测试能够像现在这样平稳地工作,所以谢谢!

配置 (Setting up)

For this project, we are going to use React, Redux, React/Redux Router (optional) and Thunk (optional) to run the app, Jest and Enzyme for testing.

对于这个项目,我们将使用React , Redux , React / Redux Router (可选)和Thunk (可选)来运行应用程序, Jest和Enzyme进行测试。

I’ll skip the setup of all those since there are many great tutorials out there about that.

我将跳过所有这些设置,因为那里有很多很棒的教程。

To set up the basics of my integration test, I’m gonna cheat a little bit and create an util function with some boilerplate code:

为了建立集成测试的基础知识,我将作弊一点,并使用一些样板代码创建util函数:

测试中 (Testing)

In your test file, you will first need to import some dependencies, your reducer and your component:

在测试文件中,首先需要导入一些依赖项,reducer和组件:

Then, on the beforeEach function, set up your integration test variables using that util function:

然后,在beforeEach函数上,使用该util函数设置集成测试变量:

(If you don’t use React Router or Thunk, you can just remove their references here and on the util function and it’s going to work the same way.)

(如果您不使用React Router或Thunk,则可以在此处和util函数上删除它们的引用,并且它们将以相同的方式工作。)

Now you’re all set to mount your component and test it. Let’s imagine this component renders a div, which displays a text coming from the reducer. When clicking on it, the text should change to another string, let’s say ‘new text’. To test that interaction, you can simply do:

现在您已经准备好安装组件并对其进行测试。 让我们想象一下这个组件渲染了一个div ,它显示了来自reducer的文本。 单击它时,文本应更改为另一个字符串,例如“新文本”。 要测试这种交互,您可以简单地执行以下操作:

That’s it ☺ With this very simple code you’re testing the div calling an action producer on click, that dispatches an action to the reducer, that changes the data, triggering a re-render on the component, that is expected to change the way you want it to change. If any of those steps fail, your test goes red and you know that functionality of your app is not working.

就是这样☺通过这个非常简单的代码,您正在测试div并在单击时调用一个动作生成器,该动作生成器将动作分派给reducer,该动作将更改数据,触发组件的重新渲染,从而有望改变方式你想改变它。 如果这些步骤中的任何一个失败,则测试会变成红色,并且您知道应用程序的功能无法正常工作。

You can try to go deeper in this chain and assert some other things:

您可以尝试深入了解此链并断言其他一些事情:

测试API调用 (Testing API calls)

In the real world you’ll probably need to call some APIs to fetch data for your app, and that is the part you need to mock in order to test things effectively. We’ll use Jest here, which is not the best way to mock http requests, but I’ll do it for the convenience.

在现实世界中,您可能需要调用一些API来获取应用程序的数据,而这是您为了进行有效测试而需要模拟的部分。 我们将在这里使用Jest,这不是模拟HTTP请求的最佳方法,但是为了方便起见,我将使用它。

Assuming you use a hypothetical http client to call an endpoint through its get function when you click on the div, then set the return of this call into the reducer that gets displayed back in the div:

假设您在单击div时使用假设的http客户端通过其get函数调用端点,然后将此调用的返回值设置到在div中显示的reducer中:

In an even more real world application, that get function will return you a Promise object. Things become a little complicated from here because the simulated click function is unaware of that promise and there is no way of executing its then function. The reference to the object has been lost.

在更真实的应用程序中,该get函数将返回一个Promise对象。 从这里开始,事情变得有些复杂,因为模拟的click函数没有意识到那个承诺,并且无法执行then函数。 对对象的引用已丢失。

We will need to somehow wait for that promise to resolve before executing the assertions. We work around this by doing a little hack in an util function:

在执行断言之前,我们将需要以某种方式等待该承诺解决。 我们通过在util函数中进行一些修改来解决此问题:

And our test is now going to look like this:

现在,我们的测试将如下所示:

With the async … await statement , available since ES7, our test is going to wait until all promises have been resolved so it can make its assertions. Jest currently has no solution for this, but this hack works pretty well in real life.

自从ES7开始使用async…await语句,我们的测试将等待直到所有promise都已解决,以便可以进行声明。 Jest目前还没有解决方案,但是此hack在现实生活中效果很好。

If you have more complicated action producers with other promises being called in the resolve or reject of that first promise, I suggest you unit test those calls and also test the final results of all cases in integration tests.

如果您有更复杂的动作生产者,而在第一个承诺的解决拒绝中调用了其他承诺,则建议您对这些调用进行单元测试,并在集成测试中测试所有案例的最终结果。

更多测试 (More Testing)

In case you need to set an initial state to your component , you can dispatch actions manually until you reach the desired state:

如果需要为组件设置初始状态,则可以手动分派操作,直到达到所需状态为止:

store.dispatch({ payload: 'data', type: 'SOME_ACTION' });

You can also go crazy on those assertions and test every little thing, or keep it simple knowing the test coverage is going to be the same as if you have added unit tests on each of the layers of this app, but with a lot less code. In addition, you are also testing how those layers connect with each other and how your app responds to user input and data store changes.

您也可以为这些断言而疯狂,测试每件事,或者保持简单,因为知道测试覆盖范围与在此应用程序的每个层上都添加了单元测试一样,但是代码却少得多。 此外,您还将测试这些层如何相互连接以及您的应用如何响应用户输入和数据存储更改。

Please leave your opinion in the comments section, there is a lot of improvements to be made here and I’m happy to modify this according to your suggestions. Thanks!

请在评论部分中留下您的意见,这里有很多改进之处,我很乐意根据您的建议进行修改。 谢谢!

NO没有单元测试?!? (Y U NO UNIT TEST?!?)

We at Wave (did I mention we’re hiring?) have done a ton of front end unit tests before and, to be honest, the majority of them have been somewhat useless. Sure, they are at the core of TDD, but some reducers and action producers unit tests are just boilerplate code and don’t add much value to the code or the TDD process.

Wave之前 ( 我们是否提到过要聘用我们吗?)之前, 我们已经进行了大量的前端单元测试,老实说,大多数测试都没有用。 当然,它们是TDD的核心,但是某些化简工具和动作生产者单元测试只是样板代码,不会为代码或TDD流程增加太多价值。

You can actually do really good TDD with integration tests only, and they are going to be useful in the future to spot broken links between your app layers and ultimately to check if your app is behaving as expected, which is what automated tests are for.

实际上,您只能使用集成测试来做真正好的TDD,并且它们在将来将很有用,可以发现您的应用程序层之间断开的链接,并最终检查您的应用程序的行为是否符合预期,这就是自动化测试的目的。

Don’t get me wrong, we still unit test edge cases that are too complicated or annoying to reproduce on integration tests, but the majority of our unit tests became useless as soon as we added integration tests like the above. In the end, it means the time we now spend thinking about, developing and fixing tests is a lot lower than it was before and they are much more effective in spotting problems in the app. So, win win ☺

别误会,我们仍然对过于复杂或烦人的边缘测试进行单元测试,以至于无法在集成测试中重现,但是一旦添加了上述集成测试,我们的大多数单元测试就变得毫无用处。 最后,这意味着我们现在花在思考,开发和修复测试上的时间比以前少了很多,并且它们在发现应用程序中的问题上更加有效。 所以,双赢☺

One problem you might find is with deep mounting, instead of shallow rendering. You might think some component trees are too complicated to mount, but I’ll say another advantage of mounting the root component is to test if the child components are being instantiated correctly. If you have connected child components, you can test them separately if you prefer. I haven’t tried shallow rendering a connected component to see if this integration test setup still works, but you can try. If you don’t like to mount and don’t have connected child components, another possibility I haven’t explored is shallow render and then manually connecting them. The important thing here is to feel comfortable with the amount and the quality of the tests you’re writing, making sure they actually help in automatically doing some regression testing and discovering hidden issues for you.

您可能会发现的一个问题是深层安装而不是浅层渲染。 您可能会认为某些组件树太复杂而无法挂载,但是我会说挂载根组件的另一个好处是测试子组件是否被正确实例化。 如果已连接子组件,则可以根据需要单独测试它们。 我没有尝试浅化呈现连接的组件以查看此集成测试设置是否仍然有效,但是您可以尝试。 如果您不喜欢挂载并且没有连接子组件,那么我还没有探讨的另一种可能性是浅渲染,然后手动连接它们。 这里重要的是让您对正在编写的测试的数量和质量感到满意,确保它们实际上有助于自动执行一些回归测试并为您发现隐藏的问题。

翻译自: https://www.freecodecamp.org/news/real-integration-tests-with-react-redux-and-react-router-417125212638/

使用React,Redux和Router进行真正的集成测试相关推荐

  1. React+Redux开发实录(一)搭建工程脚手架

    React+Redux开发实录(一)搭建工程脚手架 React+Redux开发实录(二)React技术栈一览 搭建工程脚手架 准备工作 安装node 安装git 安装一款前端IDE 推荐VSCode, ...

  2. react实战项目_React实战之React+Redux实现一个天气预报小项目

    引言 经过一段时间的React学习,React和Vue的开发确实有很大的不同,但是都是MVVM框架,因此上手没有很大的难度,这次用React+Redux开发一个天气预报小项目.源码地址:https:/ ...

  3. React+Redux仿Web追书神器

    引言 由于 10 月份做的 React Native 项目没有使用到 Redux 等库,写了一段时间想深入学习 React,有个想法想做个 demo 练手下,那时候其实还没想好要做哪一个类型的,也看了 ...

  4. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  5. React+Redux系列教程

    2019独角兽企业重金招聘Python工程师标准>>> 参考项目:https://github.com/lewis617/react-redux-tutorial 参考项目下载地址: ...

  6. React+TS学习和使用(三):React Redux和项目的路由配置

    开启学习react+ts,本篇主要是学习使用React Redux和项目的路由配置 一.React Redux 需求:使用TS+React Redux实现一个累加. A. 安装 $ yarn add ...

  7. 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用

    先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...

  8. React Redux入门

    目录 入门 我们应该什么时候使用? Redux库和工具 Redux Toolkit Redux DevTools 扩展 demo练习准备工作: 基础示例 Redux Toolkit示例 Redux术语 ...

  9. React Redux 进阶: Hooks 版本用法 Custom Context 局部 Store 实践

    React Redux 进阶: Hooks 版本用法 & Custom Context 局部 Store 实践 文章目录 React Redux 进阶: Hooks 版本用法 & Cu ...

最新文章

  1. [windows server 2008 站点系列五]一招加速域用戶的文件查找速度
  2. 【直播课】图像分类竞赛技巧与多标签分类实战
  3. Qt数据库sqlite
  4. arm架构安装rxtx_Parallels推新版本 M1芯片Mac能安装Win 10
  5. 20个简约风格网站设计作品欣赏
  6. 牛客题霸 [字符串的排列] C++题解/答案
  7. 直接输出数组的名字不一定是地址值
  8. 哪些集合不能使用迭代器_Rust能力养成之(6):集合体与迭代器
  9. android点击出现菜单,Android 点击按钮弹出菜单
  10. 1.1.0-简介-P3-CAP 分布式 高可用
  11. 直接插入排序(C语言)实现
  12. python画k线图_Python绘制K线图
  13. Sublime Text中全局查找方法
  14. ftp文件推送 linux_Linux 终端访问 FTP 及 上传下载 文件
  15. excel数据分析 - 17个计算统计类函数
  16. 推荐三个图片无损放大的软件给你
  17. 阿里云服务器价格计算器有什么用
  18. 再见2019 你好2020
  19. linux 加速度传感器数据获取,对加速度传感器的数据进行方向和坐标的转换
  20. magento 货币换算

热门文章

  1. 大话数据结构—栈与队列
  2. serial port 的操作
  3. COOKIE伪造登录网站后台
  4. poj-3667(线段树区间合并)
  5. 【JavaScript】网站源码防止被人另存为
  6. 200道物理学难题——038蚱蜢跃树
  7. iOS Application Security
  8. [USACO] Beef McNuggets
  9. 中国直销未来三五年的发展趋势[转]
  10. caffe路径正确,却读不到图片