使用React,Redux和Router進行真正的集成測試

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/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395406.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395406.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395406.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Go語言從入門到精通 - 數據類型轉換

本節核心內容 介紹 Go語言數據類型轉換的格式介紹 數據轉換代碼示例介紹 數據轉換過程中的注意事項 本小節視頻教程和代碼:百度網盤 可先下載視頻和源碼到本地,邊看視頻邊結合源碼理解后續內容,邊學邊練。 Go語言數據類型轉換 Go 語言使用類型…

JNI通過線程c回調java層的函數

1、參看博客:http://www.jianshu.com/p/e576c7e1c403 Android JNI 篇 - JNI回調的三種方法(精華篇) 2、參看博客: JNI層線程回調Java函數關鍵點及示例 http://blog.csdn.net/fu_shuwu/article/details/41121741 3 http://blog.cs…

signature=f7a4b29b93ef2b36608792fdef7f454a,Embedding of image authentication signatures

摘要:A method (), an apparatus, a computer readable medium and use of said method for authenticating an audio-visual signal (), such as a digital image or video, are disclosed. A signature is derived from all image regions, including areas with …

glob

主要是用來在匹配文件,相當shell中用通配符匹配. 用法: glob.glob(pathname) # 返回匹配的文件作為一個列表返回 glob.iglob(pathname) # 匹配到的文件名,返回一個迭代器 ps: pathname是路徑, 可以是絕對和相對路徑 匹配當前目錄下有一個數字開頭…

構建微服務:Spring boot 入門篇

Spring官方網站本身使用Spring框架開發,隨著功能以及業務邏輯的日益復雜,應用伴隨著大量的XML配置文件以及復雜的Bean依賴關系。隨著Spring 3.0的發布,Spring IO團隊逐漸開始擺脫XML配置文件,并且在開發過程中大量使用“約定優先配…

img 加載 svg占位符_如何使用SVG作為占位符以及其他圖像加載技術

img 加載 svg占位符by Jos M. Prez由JosM.Prez 如何使用SVG作為占位符以及其他圖像加載技術 (How to use SVG as a Placeholder, and Other Image Loading Techniques) I’m passionate about image performance optimisation and making images load fast on the web. One of…

hibernate 注解

參考鏈接地址:https://blog.csdn.net/wx5040257/article/details/78697119 主鍵生成策略:https://www.cnblogs.com/ph123/p/5692194.html 注解轉載于:https://www.cnblogs.com/wangxuekui/p/10287647.html

iOS - UIScrollView

前言 NS_CLASS_AVAILABLE_IOS(2_0) interface UIScrollView : UIView <NSCoding>available(iOS 2.0, *) public class UIScrollView : UIView, NSCoding 移動設備的屏幕大小是極其有限的&#xff0c;因此直接展示在用戶眼前的內容也相當有限。當展示的內容較多&…

機器學習的展望

現階段越來越多的投入到機器學習的熱潮中來&#xff0c;有的人很是興奮&#xff0c;認為這是一場新和革命&#xff0c;一場終極人工智能來臨的前夜。也有人表示悲觀&#xff0c;認為不僅機器學習不代表終極人工智能&#xff0c; 也還非常不成熟。 大量的新生代投入到這個領域&a…

BZOJ3453 XLkxc(拉格朗日插值)

顯然f(i)是一個k2項式&#xff0c;g(x)是f(i)的前綴和&#xff0c;則顯然其是k3項式&#xff0c;插值即可。最后要求的東西大膽猜想是個k4項式繼續插值就做完了。注意2p>maxint…… #include<iostream> #include<cstdio> #include<cmath> #include<cs…

電郵地址_利用這些簡單的技巧來充分利用電子郵件的強大功能

電郵地址Let’s talk about some email features that are surprisingly under-used, and that can really benefit you — if you know how to use them. This article is suitable for both users and developers who want to become email Jedi.讓我們討論一些電子郵件功能&…

inputstream重新賦值之前需要close嗎_變量提升真的搞懂了嗎?打臉的一道題

變量提升真的搞懂了嗎&#xff1f;打臉的一道題我們知道JS代碼在執行之前&#xff0c;會做一系列的事情&#xff0c;其中就包括變量提升&#xff0c;原本以為把變量提升搞懂的我&#xff08;因為這兩天一直在研究變量提升&#xff0c;自我感覺已經很良好了&#xff0c;哈哈哈&a…

html5語義化 兼容,HTML5語義化標簽,兼容性問題

HTML5不僅僅作為HTML標記語言的一個最新版本&#xff0c;更重要的是它制定了web應用開發的一系列標準&#xff0c;成為第一個將web做為應用開發平臺的HTML語言。HTML5定義了一系列的新元素&#xff0c;如新語義化標簽&#xff0c;智能表單&#xff0c;多媒體標簽等&#xff0c;…

Swift之 vm10虛擬機安裝Mac OS X10.10教程

VM10裝Mac OS X 10.9.3及更新到Mac OS X 10.10,讓你的windows也能玩Swift 。 近期WWDC放出終極大招——新的編程語言Swift(雨燕),導致一大波程序猿的圍觀和躍躍欲試。當然了,工欲善其事,必先利其器,所以對于那些沒有Mac又想要嘗鮮的小伙伴肯定非常為難。可是&#xff0c;請放…

如何使用json開發web_如何通過使用JSON Web令牌簡化應用程序的身份驗證

如何使用json開發webby Sudheesh Shetty由Sudheesh Shetty 如何通過使用JSON Web令牌簡化應用程序的身份驗證 (How to simplify your app’s authentication by using JSON Web Token) Every application we come across today implements security measures so that the user…

c++ 實現錄音并且指定到文件_通話自動錄音,留下美好回憶,記錄完整錄音證據...

手機通話&#xff0c;如果自動錄音多好&#xff0c;許多人與我一樣抱有這個想法。記得華為Android版本5.0時代&#xff0c;手機沒有自動錄音功能&#xff0c;我一直到網上下載自動通話錄音軟件&#xff0c;有時甚至是下載ROOT版的帶自動通話功能的EMUI版本進行刷機安裝。那個時…

2639-Bone Collector II (01背包之第k優解)

題目鏈接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid2639 求第k優解的關鍵代碼&#xff1a; 用兩個數組記錄兩種狀態&#xff08;選擇或不選擇&#xff09;&#xff0c;并且只要記錄前k次。在這兩個數組中都是前k次可能的最優解。所以我們只要把這兩個數組做比較…

html自動按鍵,VBS腳本和HTML DOM自動操作網頁

本來是想通過JS實現對其他頁面的控制&#xff0c;發現跨域無法獲取頁面DOM來操作。接著考慮bat&#xff0c;發現也實現不了&#xff0c;于是想到vbs。vbs還是很強大啊&#xff0c;病毒之類很多都是vbs腳本啊。vbs打開瀏覽器&#xff0c;然后通過dom來操作頁面&#xff0c;可以實…

opencv在同一窗口打印多張圖片

首先&#xff0c;由于cv2處理的圖片是通過ndarray的格式操作的&#xff0c;也就是說通過array的拼接就可以實現圖片的拼接&#xff0c;那么之后就可以通過簡單的imshow將合并的圖片打印從而達到在一個窗口中顯示多張圖片的目的。 import cv2 import numpy as npimg1 cv2.imrea…

dj打碟怎么學_學DJ打碟 - Rane聲卡連接

上一篇內容中&#xff0c;老師講過在學DJ打碟的時候&#xff0c;是離不開對軟件方面的操作&#xff0c;其實每一個學習過程&#xff0c;當你學會之后&#xff0c;在“回頭看”的時候&#xff0c;都會覺得&#xff1a;原來學DJ打碟這么簡單啊&#xff0c;這就是已經學習過的人會…