There are two aspect of testing React components: testing their structure (desired markup is displayed) and behaviour (e.g. when clicking on a button this function will be called or something different will appear in component’s markup).
Testing component structure is best done with shallow rendering since it renders only provided component and not its potential sub-components. It only renders one level deep. Unfortunately it doesn’t work with testing behaviour especially if you are using
For testing component’s behaviour you need to render component in a different way and also DOM needs to be present. DOM can be real or emulated. You get a real DOM with running your tests with browser test runners like karma (which opens a browser and runs test suits in it) and fake with libraries like jsdom or domino. The way to go is with real DOM since with fake DOM you don’t account for browser differences. But fake DOM is quicker solution because setting right configuration for karma isn’t quite straightforward and waiting for browser to open and close also takes more time.
I noticed stateless components doesn’t work with latter method. But there is hack for this and requires you to wrap the stateless component with normal component (output of stateless component goes to render method).
You should always strive to test component in isolation. The way how I do it most of the time is passing all variables and callbacks to component via props so while testing I can create fake callbacks (spies) and assert they have been called when specific event has occurred.
I use Mocha for my test runner and my assertion library of choice is unexpected with unexpected-react which simplifies asserting that component’s JSX is presented in rendered component. Previously I used expect with expect-jsx but it is not as powerful since component’s output is simply converted into string. With unexpected-react you can leave tags’
children out and still get a green test. On the other side expect also comes with methods for creating spies and stubs while with unexpected you have to rely on external library for doing that (like sinon).
All necessary methods for rendering, simulating event and finding elements in rendered component are provided by React team in form of
Testing React components personally took quite a time to figure it out and to get comfortable with it but now I’m practising it and improving my testing techniques almost on daily basis and it’s fun.