Testing react.js with spies

Marlena Compton
5 min readNov 23, 2015

--

This post takes a look at writing tests with spies in the javascript testing framework, Jasmine, for an app that uses React and one way data flow.

Meet Ned

To learn about test driving React with a flux architecture, I’ve created a very small writing app called NedNot an EDitor.

Ned consists of a record button and an area for displaying or writing text. Click the record button and you can write.

Click the record button again and Ned will show you what you wrote.

Ned implements React’s flux architecture using cursors. In particular, Ned uses a cursor library, pui-cursor. While there are other libraries for cursors, I like pui-cursor because it is small and simple.

Ned’s Components

In order to give some context for the tests I’m about to describe, I’m posting a couple of screenshots showing the components involved.

The page component is a parent component which shows the different pieces involved in the app for recording and writing. If you look at the return statement in the render method, you can see html and jsx markup that maps to what you see on the page.

The WriteText component renders the text area once the record button is clicked.

Spies for testing

The tests for Ned make use of spies in a few different ways. If you look at the documentation for Jasmine, you will see that spies are for stubbing out functions and for tracking a) the calls made to those functions and b) the arguments in those functions. Practically speaking, there are two basic situations that determine how a spy will be used: either you want to do some checking of a function’s implementation or you are simply checking that something such as an argument was called. In the 2nd case, we don’t really care about the implementation underneath, just that something was called.

Spying on functions with implementation

The Jasmine docs have a good example of setting up and using a spy on a function.

Ned has this type of spy setup happening in the test for the Application component.

The spy is set up on line 10 by passing in the component and the method I want to spy on. Notice that this isn’t actually a stub. Because I am using .and.callThrough, React’s render function will be called and my spy will be watching, which you can see on line 20. Another way of saying this is that jasmine is delegating to the implementation, as described here in their docs.

Note that all of the spy stuff is being set up in the beforeEach and my it-block consists solely of my expectation that the render method in the page component has been called.

Spying on callback arguments with create spy

Although spyOn can be used for tracking arguments to a function, sometimes you will want to track that the arguments in a callback have been called. This also helps you to test that callbacks are happening when expected.

In this case, jasmine.createSpy comes in handy. The createSpy method gives you a bare spy which as mentioned in the docs, will do all types of tracking but isn’t tied to an implementation. In the case of checking the arguments in a callback, this lets you attach the bare spy as a listener and observe the call to the bare spy without having your implementation attached.

The spy created below on line 11 is an example of this.

Notice that the spy is created using jasmine.createSpy() and is passed into a Cursor as the callback on line 12. After that, React’s render method is called and the component is passed into it. One more step and our test setup is complete.

On line 28 an event is simulated on the record component. This change event is what happens when the user clicks on the button. The change event grabs the text from the text area. In our expectation on line 32, the spy is checking that event was called with the text we passed into the cursor. We’re not checking that a particular method was called, but rather that our argument was used.

Again, the spy is completely set up in the before. The only thing that happens in the test is the check that the spy has been called.

While these are just two example usages of spies, there’s a lot more you can do with them. Spies are a great way of leveling up your testing game which is so important if you are getting going with test driven development. In fact, Jasmine isn’t the only test framework that has them. You will also find spies in Sinon.js which is used with the Mocha testing framework.

Thanks @rdy for proofreading and feedback.

--

--

Marlena Compton

Postings here are my own and don’t represent my employer.