In Redux, action creators are functions which return plain objects. When testing action creators, we want to test whether the correct action creator was called and also whether the right action was returned.
For async action creators using Redux Thunk or other middleware, it's best to completely mock the Redux store for tests. You can apply the middleware to a mock store using redux-mock-store. You can also use fetch-mock to mock the HTTP requests.
In addition to having unit tests that isolate reducers, selectors, middleware, you can verify they are all integrated correctly, by integration testing the whole store. These integration style tests will be less brittle & more resilient to to refactorings (such as switching from one type of Redux middleware to another, or renaming a selector), but also may require more mocking.
A nice thing about React components is that they are usually small and only rely on their props. That makes them easy to test.
First, we will install React Testing Library. React Testing Library is a simple and complete React DOM testing utility that encourages good testing practices. It uses react-dom's render function and act from react-dom/tests-utils. Alternatively Enzyme or React test-renderer can be used.
npm install --save-dev @testing-library/react
If you are using jest as recommended above, we also recommend installing jest-dom as it provides a set of custom jest matchers that you can use to extend jest. These will make your tests more declarative, clear to read and to maintain. jest-dom is being used in the examples below.
npm install --save-dev @testing-library/jest-dom
To test the components, we render them into the DOM and pass stubbed callbacks as props, then we assert whether the callbacks were called when expected.
To test it, we can use the wrapper option in React Testing Library's render function and export our own render function as explained in React Testing Library's setup docs.
Our render function can look like this:
// test-utils.js
importReactfrom'react'
import{ render as rtlRender }from'@testing-library/react'
We need to create a fake getState, dispatch, and next functions. We use jest.fn() to create stubs, but with other test frameworks you would likely use Sinon.
The invoke function runs our middleware in the same way Redux does.
constcreate=()=>{
const store ={
getState: jest.fn(()=>({})),
dispatch: jest.fn()
}
const next = jest.fn()
constinvoke=action=>thunk(store)(next)(action)
return{ store, next, invoke }
}
We test that our middleware is calling the getState, dispatch, and next functions at the right time.
React Testing Library: React Testing Library is a very light-weight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, in a way that encourages better testing practices. Its primary guiding principle is: "The more your tests resemble the way your software is used, the more confidence they can give you."
Enzyme: Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.
React Test Utils: ReactTestUtils makes it easy to test React components in the testing framework of your choice. React Testing Library uses the act function exported by React Test Utils.