React UnitTest without Jest

Purpose

It is difficult to UnitTest react's components.

Jest is one of the most popular test framework for react but have some problems.

So we will think about other solution for React UnitTest.

Goal

  • We can UnitTest react components
  • We can test Promise
  • We can change dependent components or modules to mock object
  • We can test even if code is jsx or es6
  • We can write codes clearly
  • We can set it easily

Outline

  • mocha based
  • By reading test target in vm.runInContext, we change content inside the "require" in test target dynamically
  • finish compiling jsx to js before testing
  • make symbollic link to "src" under "node_module", to avoid mess of relative path

the source code is:

https://github.com/uryyyyyyy/React_mocha_boilerplate/tree/my_mocker

How_to_use

Download this:

https://github.com/uryyyyyyy/React_mocha_boilerplate/tree/my_mocker

and

npm install -g gulp
npm install
ln -s ../src node_modules/

after that try

gulp test:testUtil --path src/reactComponents/_tests_/nestComponentTest.js

if you want to do mock test

var assert = require('assert')
var testMocker = require('src/testMocker.js')
describe("#mockTest", function () {
    var mock={};
    mock["src/functions/AsyncUtil.js"] = {
        hello: function hello() {
            console.log("hello mock");
        }
    };
    var util2 = testMocker.loadModule("./testSandbox/src/functions/util2.js", mock);
    it("mock hello", function () {
        util2.hello();
    });
});

you want to test hello function in src/functions/util2.js, but hello function is dependent on a method in AsyncUtil.js, we cannot UnitTest by default.

So, we create mock object of AsyncUtil.js in advance, and read util2.js by "testMocker". Then you can see mock object's method is called when you execute util2.hello().

when you want to test React Components

var assert = require('assert')
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var testMocker = require('src/testMocker.js')
var jsdom = require("jsdom");
global.document = jsdom.jsdom("<!doctype html><html><body></body></html>");
global.window = document.parentWindow;
global.navigator = window.navigator;
describe("#react nestComponent test", function () {
   var mock={};
    var NestComponent = testMocker.loadModule("./testSandbox/src/reactComponents/NestComponent.js", mock);
    it("render NestComponent, but don't render untouchableOne", function () {
        var nestComponent = TestUtils.renderIntoDocument(
            <NestComponent  />
        );
        console.log(nestComponent.calc());
        assert.equal(nestComponent.calc(), 3);
    });
});

you want to test calc function in src/reactComponents/NestComponent.js. But, react's components should be instanced when you want to test them. So we will need "jsdom" first.

And, when react' components are set on DOM, the render function will be called, so we might call unnecessary components for example above "UntouchableOne".

references

http://qiita.com/uryyyyyyy/items/edf4bebd32c5cd537177

http://qiita.com/[email protected]/items/35374e426711cb620586

https://howtonode.org/testing-private-state-and-mocking-deps

https://github.com/danvk/mocha-react

http://qiita.com/uryyyyyyy/items/edf4bebd32c5cd537177