{"id":1420,"date":"2019-08-27T16:33:19","date_gmt":"2019-08-27T13:33:19","guid":{"rendered":"https:\/\/djangostars.com\/blog\/?p=1420"},"modified":"2025-07-25T16:20:20","modified_gmt":"2025-07-25T16:20:20","slug":"unit-integration-testing-redux-react-forms","status":"publish","type":"post","link":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/","title":{"rendered":"Unit and Integration Testing of React\/Redux Forms"},"content":{"rendered":"<p>After seeing the amazing feedback and requests that followed my latest article on <a href=\"https:\/\/djangostars.com\/blog\/jest-enzyme-react-unit-testing\/\">What and How to Test with Jest and Enzyme<\/a>, I\u2019d love to share a couple of other test cases. Today, we\u2019ll talk about testing React forms that are connected with Redux, considering both unit and integration testing. Hopefully, you\u2019ll find something useful below.<\/p>\n<p>By the way, Django Stars specialists have deep expertise in both software development and testing. Check out our <a href=\"https:\/\/djangostars.com\/case-studies\/\">case studies<\/a> to learn more.<br \/>\n<!--\n\n\n<h2 id=\"Sowhat\u2019sonthe agenda?\">So, what\u2019s on the agenda?<\/h2>\n\n\n\n\n<ul>\n \t\n\n<li><a rel=\"nofollow\" href=\"#header1\">Unit vs. Integration Testing<\/a><\/li>\n\n\n \t\n\n<li><a rel=\"nofollow\" href=\"#header2\">Test Preparations: Form Review<\/a><\/li>\n\n\n \t\n\n<li><a rel=\"nofollow\" href=\"#header3\">Testing Forms Connected with Redux<\/a><\/li>\n\n\n \t\n\n<li><a rel=\"nofollow\" href=\"#header4\">Unit Testing of Forms Connected with Redux<\/a>\n\n\n<ul>\n \t\n\n<li><a rel=\"nofollow\" href=\"#header5\">Writing Tests for Unit Testing<\/a><\/li>\n\n\n<\/ul>\n\n\n<\/li>\n\n\n \t\n\n<li><a rel=\"nofollow\" href=\"#header6\">Integration Testing of Forms Connected with Redux<\/a>\n\n\n<ul>\n \t\n\n<li><a rel=\"nofollow\" href=\"#header7\">Writing Tests for Integration Testing<\/a><\/li>\n\n\n<\/ul>\n\n\n<\/li>\n\n\n<\/ul>\n\n\n--><\/p>\n<h2 id=\"header1\">Unit vs. Integration Testing<\/h2>\n<p>Before we dive deep into the subject, let\u2019s make sure we all understand the basics. There are many different types of app testing, but a <a href=\"https:\/\/gojko.net\/assets\/201802-js-research.pdf\" rel=\"nofollow\">2018 survey<\/a> shows that automated unit and integration tests are at the top of the list.<br \/>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-1415\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2019\/08\/types-of-testing.png\" alt=\"types-of-testing\" width=\"1210\" height=\"839\" \/><br \/>\nFor a better comparison, I\u2019m only picking the two main automated testing methods. Let\u2019s look at the definitions and characteristics of unit and integration testing:<br \/>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-1419\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2019\/08\/automated-testing-methods.png\" alt=\"automated-testing-methods\" width=\"1544\" height=\"1514\" \/><\/p>\n<h2 id=\"header2\">Test Preparations: Form Review<\/h2>\n<p>Before you start any job, you want to know all about it. You don\u2019t want any surprises, and you do want the best results. This is also true for testing. Which is why it\u2019s better to <strong>get all the available information on the form that should be tested, and its related conditions <\/strong>beforehand. And, of course, to make sure you know what exactly should be tested.<\/p>\n<p>To show you how it goes, I chose a form that contains information on <strong>Property Evaluation<\/strong>. It\u2019s a form that customers fill in to describe the property they would like to purchase. It\u2019s quite simple \u2013 it doesn\u2019t have any complex logic or mandatory fields, and a few fields to fill in.<\/p>\n<p>Check out the image below:<br \/>\n<img decoding=\"async\" class=\"alignnone size-full wp-image-1417\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2019\/08\/moneypark-screen2.png\" alt=\"moneypark-form\" width=\"2011\" height=\"1301\" \/><br \/>\n<!-- [case-study-banner image=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2022\/10\/Case-Studies-Money-Park.png\" title=\"Money Park\" logo=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2019\/05\/logo_mp-2x.png\" link=\"https:\/\/djangostars.com\/case-studies\/moneypark\/\" small_text=\"The first independent provider of personalized financial advice on mortgage and insurance products in Switzerland\" ] --><br \/>\nThe only logic you can\u2019t see in the image are different fields that are set depending on the choice in the `Property type` field. For instance:<\/p>\n<ul>\n<li>If a customer chooses \u2018Apartment\u2019, they get options like \u2018floor\u2019, \u2018parking conditions\u2019, etc.<\/li>\n<li>If a customer chooses \u2018House\u2019, they get options like \u2018floor area\u2019, \u2018building standard\u2019, etc.<\/li>\n<\/ul>\n<p><div class=\"new_shortcode_box shortcode_case_box case\" style=\"background-image: url(https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2022\/10\/Case-Studies-Money-Park.png)\">\n\t\t<div class=\"green_block\"><\/div>\n\t\t<div class=\"content\">\n\t\t\t<div class=\"title\">Money Park<\/div>\n\t\t\t<div class=\"content_holder\">\n                <div class=\"description\">\n                The first independent provider of personalized financial advice on mortgage and insurance products in Switzerland\n                <\/div>\n                <div class=\"link\">\n                    <a href=\"https:\/\/djangostars.com\/case-studies\/moneypark\/\">\n                                <span>Learn more<\/span>\n                                <div class=\"button_animated\">\n                                    <svg width=\"24\" height=\"12\" viewBox=\"0 0 24 12\" fill=\"none\"\n                                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                                        <path d=\"M23.725 5.33638C23.7248 5.3361 23.7245 5.33577 23.7242 5.33549L18.8256 0.460497C18.4586 0.0952939 17.865 0.096653 17.4997 0.463684C17.1345 0.830668 17.1359 1.42425 17.5028 1.7895L20.7918 5.06249H0.9375C0.419719 5.06249 0 5.48221 0 5.99999C0 6.51777 0.419719 6.93749 0.9375 6.93749H20.7917L17.5029 10.2105C17.1359 10.5757 17.1345 11.1693 17.4998 11.5363C17.865 11.9034 18.4587 11.9046 18.8256 11.5395L23.7242 6.66449C23.7245 6.66421 23.7248 6.66388 23.7251 6.6636C24.0923 6.29713 24.0911 5.70163 23.725 5.33638Z\"\n                                              fill=\"#282828\"><\/path>\n                                    <\/svg>\n                         <div class=\"shape\"><\/div>\n                       <\/div>\n                    <\/a>\n                <\/div>\n\t\t    <\/div>\n\t\t<\/div>\n\t<\/div><br \/>\nNext, let\u2019s dive into the form\u2019s code. The implementation of the form is divided into two parts:<\/p>\n<ol>\n<li>Template file &#8211; listing of all fields; we can also call it \u2018view\u2019 (Code Listing of <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/property-details\/PropertySelfOwnedForm.js\" rel=\"nofollow\">PropertySelfOwnedForm.js<\/a> on github)<\/li>\n<li>Container file &#8211; form logic, stored in one place (Code Listing of <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/property-details\/PropertySelfOwnedFormContainer.js\" rel=\"nofollow\">PropertySelfOwnedFormContainer.js<\/a> on github)<\/li>\n<\/ol>\n<h2 id=\"header3\">Testing Forms Connected with Redux<\/h2>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-1416\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2019\/08\/testing-forms-connected-with-redux.png\" alt=\"testing-forms-connected-with-redux\" width=\"1414\" height=\"1071\" \/><br \/>\nDepending on the type of testing, I use different processes to test forms connected with Redux.<\/p>\n<p>For <strong>unit tests<\/strong>, I use shallow rendering (as opposed to deep tree rendering) and the Redux-mock-store library. For <strong>integration tests<\/strong>, I use mount rendering (deep tree rendering) and an actual Redux store.<\/p>\n<h2 id=\"header4\">Unit Testing of Forms Connected with Redux<\/h2>\n<p>As I said above, for unit testing I use shallow rendering. It\u2019s a one-level rendering that doesn\u2019t take into account child components inside the component in question. On top of this, the tested component doesn\u2019t indirectly affect its child components behavior.<br \/>\n<a href=\"https:\/\/github.com\/reduxjs\/redux-mock-store\" rel=\"nofollow\">Redux-mock-store<\/a> is a library designed to test action logic, and provides a mocked Redux store. It\u2019s easy to launch and to use, and doesn\u2019t affect the Redux store itself.<\/p>\n<p>Before you start Redux testing, be sure to configure the form.<\/p>\n<p>These are my imports:<\/p>\n<ul>\n<li>Rendering method: Enzyme&#8217;s shallow renderer<\/li>\n<li>Include mocked data required for form rendering. In the example below it is json file djangoParamsChoices, containing mocked data for select options. This data is being passed to context on the backend side and fetched on the frontend side through the custom function `getDjangoParam`.<\/li>\n<li>Include form view itself<\/li>\n<li>Import additional tools for store mock<\/li>\n<li>Import additional libraries for test needs (mainly required when writing the special test case)<\/li>\n<\/ul>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Imports+for+Unit+Form+Testing%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div>\n<ul>\n<li>Initialize mockstore with empty state:<\/li>\n<\/ul>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Initialize+mockstore+with+empty+state%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div>\n<ul>\n<li>Set default props (they vary from the tested form requirements):<\/li>\n<\/ul>\n<p style=\"padding-left: 40px;\">The form view depends on the property type; that\u2019s why I put in default props.<\/p>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Set+default+props%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div>\n<ul>\n<li>Mock store and render form before each test:<\/li>\n<\/ul>\n<p style=\"padding-left: 40px;\">First, configure the mock store with the help of the redux-mock-store library.<\/p>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Configure+mock+store+with+redux-mock-store+library%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div>\n<ul>\n<li>Configure function for execution before each test run using the \u2018beforeEach\u2019 method.<\/li>\n<\/ul>\n<p><div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28beforeEach+function+configuration%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nInside the function, don\u2019t forget to:<\/p>\n<ol>\n<li>Reset the store after every test: <code>`store = mockStore(initialState)`<\/code> returns an instance of the configured mock store.<\/li>\n<li>Make Wrapper HOC to pass store, defaultProps and custom props for the special test case<\/li>\n<li>Do the form rendering using the `.dive()` method to receive the rendered form structure one level deeper.<\/li>\n<\/ol>\n<p>Without the dive() method, ShallowWrapper looks like this:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28ShallowWrapper+without+dive%28%29+method%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nHere\u2019s what it looks like with the dive() method: <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/ShallowWrapperWithDiveMethod.js\" rel=\"nofollow\">ShallowWrapperWithDiveMethod.js<\/a><\/p>\n<h3 id=\"header5\">Writing Tests for Unit Testing<\/h3>\n<p>Now, you\u2019re ready to write the test itself. Follow my process to see how you should proceed.<\/p>\n<p>Check the Form Component that\u2019s being rendered:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Render+form+component%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nCheck the list of fields rendered correctly for property type \u2018House\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Check+render+of+PropertyTypeHouse%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nCreate a snapshot to check the user interface for property type \u2018House\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Create+form+snapshot+for+PropertyTypeHouse%29+PropertySelfOwnedFormUnit.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nAt this point, you must be asking yourself, \u201cWhy do we need two tests for one property type, both snapshot and field existence?\u201d Here\u2019s why: the two tests help us check logic and UI.<\/p>\n<ul>\n<li>According to the logic, we should receive an expected list of fields<\/li>\n<li>According to the UI, we should obtain a defined order of fields with its own design.<\/li>\n<\/ul>\n<p>This is what we get from the two tests:<\/p>\n<ul>\n<li>No changes in field list \/ UI -&gt; Two tests passed<\/li>\n<li>No changes in field list \/ Changes in UI -&gt; Snapshot test failed, i.e., the UI changed.<\/li>\n<li>Changes in field list \/ Changes in UI -&gt; Both tests failed, i.e., the logic failed (or both logic and UI), as the field list differs from what was expected.<\/li>\n<\/ul>\n<p>Having gone through two tests, I see exactly what the problem was and where I should look for reasons for failure. I repeat the process with another property type \u2013 \u2018Apartment\u2019 and its expected array of fields. I follow the same steps:<\/p>\n<p>Check the list of fields rendered correctly for property type \u2018Apartment\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Check+render+of+PropertyTypeApartment%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nCreate a snapshot to check fields for property type \u2018Apartment\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Create+form+snapshot+forPropertyTypeApartment%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThe next test is experimental. I decided to investigate a <a href=\"https:\/\/github.com\/jest-community\/snapshot-diff\" rel=\"nofollow\">diffing snapshot utility for Jest<\/a> that one reader of my recent article suggested.<\/p>\n<p>First of all, let\u2019s see how it works. It receives two rendered components with different states or props, and outputs their difference as a string. In the example below, I created a snapshot showing the difference between the forms with different property types \u2013 \u2018House and \u2018Apartment\u2019.<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Check+snapshot+difference+between+2+forms%29+PropertySelfOwnedFormUnit.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThis kind of test has its advantages. As you can see above, it covers two snapshots and minimizes code base \u2013 thus, instead of two snapshots, you can create just one showing the difference, and similarly, only write one test instead of two. It\u2019s quite easy to use, and lets you cover different states with one test. But, looking at my case, I got a snapshot with 2841 rows, as shown on <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/SnapshotDiffBetween2Forms.js\" rel=\"nofollow\">github<\/a>. With a large amount of code like this, it\u2019s too hard to see why the test had failed and where.<\/p>\n<p>This only proves one thing: whatever you work with, use your tools and libraries wisely, and only in the places that really require it. This utility may be useful for testing differences in stateless components to find UI inconsistencies, and to define differences in simple functionality components that contain minimum logical conditions. But for testing large pieces of UI, it doesn\u2019t seem to be appropriate.<\/p>\n<p>Before we wrap up the part about unit testing of forms connected with Redux, there\u2019s one more thing. There\u2019s a reason why I didn\u2019t include tests for events. Let\u2019s look at the form structure PropertySelfOwnedForm.js that includes the <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/shared\/buttons\/ButtonsToolbar.js\" rel=\"nofollow\">ButtonsToolbar.js<\/a> component.<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Import+ButtonsToolbar+component%29+PropertySelfOwnedForm.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThis component contains three buttons: \u2018Save\u2019, \u2018Save and Next\u2019 and \u2018Next\u2019, and is used in many forms. Shallow rendering doesn\u2019t include child components, and at this point, I don\u2019t care about their functionality. And rendered `ButtonsToolbar`component looks like this:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28ButtonsToolbar+shallow+rendering%29+ButtonsToolbar.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThe truth is, I don\u2019t need to test it as a part of unit form tests. I will test the button events separately in <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/shared\/buttons\/__tests__\/ButtonsToolbar.test.js\" rel=\"nofollow\">ButtonsToolbar.test.js<\/a>. <strong>You can find the full tests listing here<\/strong>: <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/property-details\/__tests__\/PropertySelfOwnedFormUnit.test.js\" rel=\"nofollow\">PropertySelfOwnedFormUnit.test.js<\/a><\/p>\n<h2 id=\"header6\">Integration Testing of Forms Connected with Redux<\/h2>\n<p>For integration testing \u2013 testing components in a working environment \u2013 I use mount rendering. Mount rendering is a type of deep level rendering that includes all the child components by mounting them all into the DOM.<\/p>\n<p>This kind of rendering is actually quite similar to the real DOM tree, as its components\u2019 behavior is interconnected. And the goal of the integration testing is to check this connection. Thus, an actual Redux store is in this case a great choice.<\/p>\n<p>An actual Redux store is one created with the help of a `redux` library. In this case, there\u2019s no need to mock anything, as you can use the real store the same way as in the app.<\/p>\n<p>Next, I\u2019m configuring my form for testing React components that connect to Redux.<\/p>\n<p>Here\u2019s the list of imports:<\/p>\n<ul>\n<li>Rendering method: Enzyme&#8217;s mount renderer<\/li>\n<li>Methods from Redux for creating a store and combining reducers into a single root reducer<\/li>\n<li>Provider from react-redux library to make store available for nested components wrapped in the connect() function<\/li>\n<li>Router from react-router-dom to provide React Router navigation<\/li>\n<li>Redux-form for better managing the redux state of the form<\/li>\n<li>propertyDetailsResource is an object with namespace and endpoint<\/li>\n<li>Include json file djangoParamsChoices, containing mocked data passed from the backend<\/li>\n<li>Include form view itself<\/li>\n<\/ul>\n<p><div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Imports+for+Integration+Testing%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThen, I prepare data for testing. To do so, it\u2019s important to keep in mind that:<\/p>\n<ul>\n<li>There\u2019s a configuration difference between defaultProps for unit and integration tests:\n<ul>\n<li>With integration tests, a resource with an actual endpoint is added to defaultProps<\/li>\n<li>Mocked function handleSubmit is provided by the &#8216;redux-form&#8217;, because Redux-Form decorates the component with the handleSubmit prop<\/li>\n<li>Three mocked functions for custom buttons submit events.<\/li>\n<\/ul>\n<\/li>\n<li>The store is created the same way as in the app<\/li>\n<li>The imported form is decorated with reduxForm<\/li>\n<li>The decorated form is wrapped by Router and Provider.<\/li>\n<\/ul>\n<p>If it makes it easier for you, the sequence of data preparation for integration testing is the same as it is for actions during the form integration with Redux.<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Data+preparation+for+integration+testing%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nRender form before each test:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Render+form+before+each+test%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><\/p>\n<h3 id=\"header7\">Writing Tests for Integration Testing<\/h3>\n<p>Now, let\u2019s do the actual writing. The first step is to create snapshots of both property types. This means that, first, you create a snapshot to check the fields for property type House\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Create+snapshot+for+PropertyTypeHouse+with+mount+rendering%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nNext, create a snapshot to check fields for property type \u2018Apartment\u2019:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Create+snapshot+forPropertyTypeApartment+with+mount+rendering%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThe form buttons are disabled if the form is a pristine or in submitting state. The following test checks if the \u2018Save\u2019 button reacts to form changes and becomes active after losing the pristine state:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Check+if+%60Save%60+button+react+to+form+changes%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nThe last three tests check events that are called by clicking on the onSubmit, onSubmitAndNavigate, or the onNavigate button.<\/p>\n<p>Check if an onSubmit event was called:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Event+simulation+on+%60Save%60+button%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\nCheck if an onSubmitAndNavigate event was called:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Event+simulation+on+%60Save+%26+continue%60+button%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><\/p>\n<p>Check if an onNavigate event was called:<br \/>\n<div class=\"oembed-gist\"><script src=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7.js?file=%28Event+simulation+on+%60Next%60+button%29+PropertySelfOwnedFormIntegration.test.js\"><\/script><noscript>View the code on <a href=\"https:\/\/gist.github.com\/ned-alyona\/8abeea442bd12bd347b29ec8aeef51d7\">Gist<\/a>.<\/noscript><\/div><br \/>\n<strong>Full tests listing<\/strong>: <a href=\"https:\/\/github.com\/ned-alyona\/react-redux-forms-testing\/blob\/master\/property-details\/__tests__\/PropertySelfOwnedFormIntegration.test.js\" rel=\"nofollow\">PropertySelfOwnedFormIntegration.test.js<\/a><\/p>\n<p>Now the form is fully tested, including the inside components being rendered.<\/p>\n<p>To conclude, I\u2019d like to say that both unit and integration testing are equally important. Each type of testing does its own work and has its own purpose. Dismissing one can lead to a lot of troubleshooting work in the future.<\/p>\n<p><a href=\"https:\/\/djangostars.com\/blog\/jest-enzyme-react-unit-testing\/\">React unit testing<\/a> mainly covers the user interface, while integration tests dig deeper into functionality. Some people find it redundant to do both, but I\u2019d say both are necessary if you want your product to look good to the user, be user-friendly, and also work smoothly. Unit testing alone will never cover the most important part of the product \u2013 the interactions among components. Besides, it\u2019s better to be safe than sorry.<\/p>\n<p>When it comes to testing, forms require special attention, as forms are an essential part of many projects and a way to communicate with customers. Which is why it\u2019s vital to be properly prepared and carefully go through all the stages \u2013 imports, mocks preparation, store creation, form decoration with Redux, and correct wrapper creation. But the tests themselves are not complicated. In most cases, they follow form logic and reflect field changes and button simulations (in the case of integration testing).<\/p>\n<p>Thank you for your time. I look forward to reading your feedback!<\/p>\n<p>If you still have questions about unit testing of Redux components or are looking for an experienced team to develop and test your product at a professional level, <a href=\"https:\/\/djangostars.com\/get-in-touch\/\">let us know<\/a>. Our specialists will gladly provide you with the advice and assistance you need.<br \/>\n<div class=\"lead-form-wrapper lets_disqus\">\n    <div class=\"lead-form transparent-footer\">\n        <p class=\"discuss-title paragraph-discuss col-md-12\">Have an idea? Let&#039;s discuss!<\/p>\n\n        \n<div class=\"wpcf7 no-js\" id=\"wpcf7-f2589-o1\" lang=\"en-US\" dir=\"ltr\" data-wpcf7-id=\"2589\">\n<div class=\"screen-reader-response\"><p role=\"status\" aria-live=\"polite\" aria-atomic=\"true\"><\/p> <ul><\/ul><\/div>\n<form action=\"\/blog\/wp-json\/wp\/v2\/posts\/1420#wpcf7-f2589-o1\" method=\"post\" class=\"wpcf7-form init\" aria-label=\"Contact form\" enctype=\"multipart\/form-data\" novalidate=\"novalidate\" data-status=\"init\">\n<div style=\"display: none;\">\n<input type=\"hidden\" name=\"_wpcf7\" value=\"2589\" \/>\n<input type=\"hidden\" name=\"_wpcf7_version\" value=\"6.0.6\" \/>\n<input type=\"hidden\" name=\"_wpcf7_locale\" value=\"en_US\" \/>\n<input type=\"hidden\" name=\"_wpcf7_unit_tag\" value=\"wpcf7-f2589-o1\" \/>\n<input type=\"hidden\" name=\"_wpcf7_container_post\" value=\"0\" \/>\n<input type=\"hidden\" name=\"_wpcf7_posted_data_hash\" value=\"\" \/>\n<input type=\"hidden\" name=\"form_start_time\" value=\"1777320688\" \/>\n<input type=\"hidden\" name=\"_wpcf7_recaptcha_response\" value=\"\" \/>\n<\/div>\n<div class=\"form_holder\">\n    <div class=\"input_section input_row\">\n        <div class=\"input_holder\">\n                            <span class=\"input_label\">\n                               Your name *\n                            <\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text wpcf7-validates-as-required\" id=\"your-name\" aria-required=\"true\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"text-898\" \/>\n\n            <input class=\"wpcf7-form-control wpcf7-hidden\" id=\"uniq_ga_id\" value=\"\" type=\"hidden\" name=\"uniq_ga_id\" \/>\n        <\/div>\n        <div class=\"input_holder\">\n                            <span class=\"input_label\">\n                                Your email *\n                            <\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-email wpcf7-validates-as-required wpcf7-text wpcf7-validates-as-email\" id=\"your-email\" aria-required=\"true\" aria-invalid=\"false\" value=\"\" type=\"email\" name=\"email-882\" \/>\n        <\/div>\n    <\/div>\n    <div class=\"input_section single_input_row\">\n        <div class=\"input_holder\">\n            <span class=\"input_label\">How can we help you? *<\/span>\n            <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text\" id=\"message\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"message\" \/>\n        <\/div>\n    <\/div>\n    <div class=\"file_attach\">\n        <input size=\"40\" class=\"wpcf7-form-control wpcf7-file\" accept=\"audio\/*,video\/*,image\/*\" aria-invalid=\"false\" type=\"file\" name=\"file-930\" \/>\n        <div class=\"file_placeholder\">\ud83d\udcce <span>Attach File<\/span>\n            <span class=\"file_formats\">Formats: pdf, doc, docx, rtf, ppt, pptx.<\/span><\/div>\n    <\/div>\n    <div class=\"checkbox_row\">\n        <div class=\"single_checkbox\"><div class=\"checkbox_indicator\"><div class=\"checked_indicator\"><svg width=\"14\" height=\"12\" viewBox=\"0 0 14 12\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M4.66804 12L0 7.26951L1.22426 6.05269L4.54927 9.40456L12.6737 0L14 1.10613L4.66804 12Z\" fill=\"#1E232C\"\/><\/svg><\/div><\/div><input type=\"checkbox\" name=\"agree\" id=\"privacy\" value=\"agree privacy\"><label for=\"privacy\" class=\"\">I have read and accepted <a href=\"https:\/\/djangostars.com\/privacy-policy\/\" style=\"margin-left: 6px;\"> Privacy Policy*<\/a><\/label><\/div>\n        <div class=\"single_checkbox\"><div class=\"checkbox_indicator\"><div class=\"checked_indicator\"><svg width=\"14\" height=\"12\" viewBox=\"0 0 14 12\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M4.66804 12L0 7.26951L1.22426 6.05269L4.54927 9.40456L12.6737 0L14 1.10613L4.66804 12Z\" fill=\"#1E232C\"\/><\/svg><\/div><\/div><input type=\"checkbox\" name=\"agree\" id=\"marketing\" value=\"agree for marketing\"><label for=\"marketing\" class=\"\">I agree to receive marketing content from Django Stars<\/label><\/div>\n    <\/div>\n    <div class=\"submit\"><button type=\"submit\"><span>send message<\/span><\/button><div class=\"safeguard\">We safeguard your privacy<\/div><\/div>\n<\/div>\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\">\n    <input size=\"40\" maxlength=\"400\" class=\"wpcf7-form-control wpcf7-text\" aria-invalid=\"false\" value=\"\" type=\"text\" name=\"website_url\" \/>\n<\/div><script type='text\/javascript'>\n\n\t\t\t\t\t\tif(contactform === undefined){\n\t\t\t\t\t\t\tvar contactform = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar innerVal = [2589,'mail_sent_ok','Thank you for your message. It has been sent.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'mail_sent_ng','There was an error trying to send your message. Please try again later.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'validation_error','One or more fields have an error. Please check and try again.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'spam','There was an error trying to send your message. Please try again later.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'accept_terms','You must accept the terms and conditions before sending your message.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_required','The field is required.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_too_long','The field is too long.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_too_short','The field is too short.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_failed','There was an unknown error uploading the file.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_file_type_invalid','You are not allowed to upload files of this type.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_file_too_large','The file is too big.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'upload_failed_php_error','There was an error uploading the file.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_date','The date format is incorrect.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'date_too_early','The date is before the earliest one allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'date_too_late','The date is after the latest one allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_number','The number format is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'number_too_small','The number is smaller than the minimum allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'number_too_large','The number is larger than the maximum allowed.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'quiz_answer_not_correct','The answer to the quiz is incorrect.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_email','The e-mail address entered is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_url','The URL is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'invalid_tel','The telephone number is invalid.'];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\tvar innerVal = [2589,'gdpr',''];\n\t\t\t\t\t\tcontactform.push(innerVal);\n\t\t\t\t\t\t<\/script><div class=\"wpcf7-response-output\" aria-hidden=\"true\"><\/div>\n<\/form>\n<\/div>\n    <\/div>\n\n    <div class=\"success_disqus\">\n        Thank you for your message.\n        <span>We\u2019ll contact you shortly<\/span>.\n    <\/div>\n<\/div>\n\n<script>\n    \/\/ (function ($) {\n    function click_input() {\n        jQuery('.file_placeholder').on('click', function () {\n            jQuery(this).parent().find('input').click();\n        })\n    }\n\n    document.addEventListener(\"DOMContentLoaded\", click_input);\n\n    \/\/ })(jQuery)\n<\/script>\n\n\n<br \/>\n<div class=\"dj-main-article-faq\" style=\"padding-top: 0px;\">\n\t\t<div class=\"dj-main-article-faq-title\">\n\t\tFrequently Asked Questions\n\t\t<\/div>\n\t\t<div class=\"dj-main-article-faq-items\">\n\t\t\t<div class=\"dj-main-article-faq-accordeon accordeon\"><dl>\n\t\t\t\t<dt>How do you test a Redux component? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Testing a Redux component involves testing both the component's behavior and its interactions with the Redux store. There are many different types of app testing, but automated unit and integration tests are at the top of the list. It's also important to get all the available information on the form that should be tested and its related conditions beforehand.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>Why is it important to test Redux forms? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>When it comes to testing, forms require special attention, as forms are an essential part of many projects and a way to communicate with customers. Which is why it\u2019s vital to be properly prepared and carefully go through all the stages \u2013 imports, mocks preparation, store creation, form decoration with Redux, and correct wrapper creation.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>Which is more suitable for integration and functional testing? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Depending on the type of testing, I use different processes to test forms connected with Redux. For unit tests, I use shallow rendering (as opposed to deep tree rendering) and the Redux-mock-store library. For integration tests, I use mount rendering (deep tree rendering) and an actual Redux store.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>What is the difference between unit testing and integration testing? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Unit testing is focused on testing individual units of code or modules in isolation, while integration testing is focused on testing how several modules work together. Both testing types are important for ensuring the reliability and stability of a software application and are usually used in combination to provide a comprehensive testing strategy.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>Which is better unit testing or integration testing for web development? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Both unit and integration testing are essential for web development and should be used in combination to provide a comprehensive testing strategy. Unit testing is helpful for catching bugs early in the development process and for ensuring that individual units of code are working as expected. Integration testing, on the other hand, is important for catching integration bugs and for ensuring that the entire application is working as expected in a production-like environment.<\/dd>\n\t\t\t<\/dl><\/div>\n\t\t\t<\/div>\n\t\t<\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After seeing the amazing feedback and requests that followed my latest article on What and How to Test with Jest and Enzyme, I\u2019d love to share a couple of other test cases. Today, we\u2019ll talk about testing React forms that are connected with Redux, considering both unit and integration testing. Hopefully, you\u2019ll find something useful [&hellip;]<\/p>\n","protected":false},"author":15,"featured_media":3551,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[44,70],"tags":[51,24],"class_list":["post-1420","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python-django","category-qa","tag-frontend","tag-quality-assurance"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Software Development Blog &amp; IT Tech Insights | Django Stars<\/title>\n<meta name=\"description\" content=\"Testing is crucial in development, but no single test provides all the answers. Learn the value of unit and integration testing for forms, and why both are essential.\" \/>\n<link rel=\"canonical\" href=\"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/1420\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unit and Integration Testing of Redux\/React Forms\" \/>\n<meta property=\"og:description\" content=\"Testing is an important part of any development process, but no single test will give you all the answers you need. Here, we talk about what unit and integration testing of forms gives you, and why you shouldn\u2019t dismiss one in favor of the other.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\" \/>\n<meta property=\"og:site_name\" content=\"Software Development Blog &amp; IT Tech Insights | Django Stars\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/djangostars\/\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-27T13:33:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-07-25T16:20:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/djangostars.com\/blog\/uploads\/2019\/08\/Cover-9.png\" \/>\n<meta name=\"author\" content=\"Alyona Pysarenko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Unit and Integration Testing of Redux\/React Forms\" \/>\n<meta name=\"twitter:description\" content=\"Testing is an important part of any development process, but no single test will give you all the answers you need. Here, we talk about what unit and integration testing of forms gives you, and why you shouldn\u2019t dismiss one in favor of the other.\" \/>\n<meta name=\"twitter:creator\" content=\"@djangostars\" \/>\n<meta name=\"twitter:site\" content=\"@djangostars\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alyona Pysarenko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\"},\"author\":{\"name\":\"Alyona Pysarenko\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5\"},\"headline\":\"Unit and Integration Testing of React\/Redux Forms\",\"datePublished\":\"2019-08-27T13:33:19+00:00\",\"dateModified\":\"2025-07-25T16:20:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\"},\"wordCount\":2598,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg\",\"keywords\":[\"Frontend\",\"Testing\"],\"articleSection\":[\"Python &amp; Django\",\"QA\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\",\"url\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\",\"name\":\"Unit and Integration Testing of React\/Redux Forms | Django Stars\",\"isPartOf\":{\"@id\":\"https:\/\/djangostars.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg\",\"datePublished\":\"2019-08-27T13:33:19+00:00\",\"dateModified\":\"2025-07-25T16:20:20+00:00\",\"author\":{\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5\"},\"description\":\"Testing is crucial in development, but no single test provides all the answers. Learn the value of unit and integration testing for forms, and why both are essential.\",\"breadcrumb\":{\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage\",\"url\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg\",\"contentUrl\":\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg\",\"width\":1440,\"height\":620,\"caption\":\"Unit and Integration Testing of ReactRedux Forms\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/djangostars.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Unit and Integration Testing of React\/Redux Forms\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/djangostars.com\/blog\/#website\",\"url\":\"https:\/\/djangostars.com\/blog\/\",\"name\":\"Software Development Blog &amp; IT Tech Insights | Django Stars\",\"description\":\"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/djangostars.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5\",\"name\":\"Alyona Pysarenko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/djangostars.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a15268f619d10a27871d8fa2db4cb2a8cc2e444e78aa3a899a1e539e5474a5ba?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a15268f619d10a27871d8fa2db4cb2a8cc2e444e78aa3a899a1e539e5474a5ba?s=96&d=mm&r=g\",\"caption\":\"Alyona Pysarenko\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/nedelchenko-alyona-2663bb78\/\"],\"url\":\"https:\/\/djangostars.com\/blog\/author\/alona-pysarenko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Testing is crucial in development, but no single test provides all the answers. Learn the value of unit and integration testing for forms, and why both are essential.","canonical":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/1420","og_locale":"en_US","og_type":"article","og_title":"Unit and Integration Testing of Redux\/React Forms","og_description":"Testing is an important part of any development process, but no single test will give you all the answers you need. Here, we talk about what unit and integration testing of forms gives you, and why you shouldn\u2019t dismiss one in favor of the other.","og_url":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/","og_site_name":"Software Development Blog &amp; IT Tech Insights | Django Stars","article_publisher":"https:\/\/www.facebook.com\/djangostars\/","article_published_time":"2019-08-27T13:33:19+00:00","article_modified_time":"2025-07-25T16:20:20+00:00","og_image":[{"url":"https:\/\/djangostars.com\/blog\/uploads\/2019\/08\/Cover-9.png","type":"","width":"","height":""}],"author":"Alyona Pysarenko","twitter_card":"summary_large_image","twitter_title":"Unit and Integration Testing of Redux\/React Forms","twitter_description":"Testing is an important part of any development process, but no single test will give you all the answers you need. Here, we talk about what unit and integration testing of forms gives you, and why you shouldn\u2019t dismiss one in favor of the other.","twitter_creator":"@djangostars","twitter_site":"@djangostars","twitter_misc":{"Written by":"Alyona Pysarenko","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#article","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/"},"author":{"name":"Alyona Pysarenko","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5"},"headline":"Unit and Integration Testing of React\/Redux Forms","datePublished":"2019-08-27T13:33:19+00:00","dateModified":"2025-07-25T16:20:20+00:00","mainEntityOfPage":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/"},"wordCount":2598,"commentCount":0,"image":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg","keywords":["Frontend","Testing"],"articleSection":["Python &amp; Django","QA"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/","url":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/","name":"Unit and Integration Testing of React\/Redux Forms | Django Stars","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage"},"image":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg","datePublished":"2019-08-27T13:33:19+00:00","dateModified":"2025-07-25T16:20:20+00:00","author":{"@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5"},"description":"Testing is crucial in development, but no single test provides all the answers. Learn the value of unit and integration testing for forms, and why both are essential.","breadcrumb":{"@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#primaryimage","url":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg","contentUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2021\/12\/Unit-and-Integration-Testing-of-ReactRedux-Forms.jpg","width":1440,"height":620,"caption":"Unit and Integration Testing of ReactRedux Forms"},{"@type":"BreadcrumbList","@id":"https:\/\/djangostars.com\/blog\/unit-integration-testing-redux-react-forms\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/djangostars.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Unit and Integration Testing of React\/Redux Forms"}]},{"@type":"WebSite","@id":"https:\/\/djangostars.com\/blog\/#website","url":"https:\/\/djangostars.com\/blog\/","name":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/djangostars.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/9c46d946e51c5e426ba3a13c642cc0d5","name":"Alyona Pysarenko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a15268f619d10a27871d8fa2db4cb2a8cc2e444e78aa3a899a1e539e5474a5ba?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a15268f619d10a27871d8fa2db4cb2a8cc2e444e78aa3a899a1e539e5474a5ba?s=96&d=mm&r=g","caption":"Alyona Pysarenko"},"sameAs":["https:\/\/www.linkedin.com\/in\/nedelchenko-alyona-2663bb78\/"],"url":"https:\/\/djangostars.com\/blog\/author\/alona-pysarenko\/"}]}},"_links":{"self":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/1420","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/comments?post=1420"}],"version-history":[{"count":30,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/1420\/revisions"}],"predecessor-version":[{"id":9274,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/1420\/revisions\/9274"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media\/3551"}],"wp:attachment":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media?parent=1420"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/categories?post=1420"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/tags?post=1420"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}