Search code examples
javascriptunit-testingrequirejsqunit

Reset module in unit tests


I have a requirejs module created with the following pattern:

// foo.js
define(function(){

    var x = 0;

    function doStuff(){
        return ++x;
    }

    return { doStuff: doStuff };

});

And a QUnit test which looks something like this:

// testfoo.js
define(['QUnit, foo'], function(QUnit, foo){

    function setup(){
        //...?
    }        

    function teardown(){
       //...?
    }

    function runTests(){

         QUnit.test('foo counter remains at 1 on multiple tests', function(assert){
              assert.equal(foo.doStuff(), 1); // this will work
         });

         QUnit.test('foo counter remains at 1 on multiple tests', function(assert){
              assert.equal(foo.doStuff(), 1); // this obviously won't
         });
     }

     return runTests;
});

How can I reset foo for each test?

I would like to keep foo a revealing module, i.e. not converting it to a constructor function with an altered prototype.

I tried var foo = require('foo');, but since requirejs is AMD based, it will complain about things getting loaded in the wrong order.


Solution

  • I suggest checking out SquireJS to create an isolated context for your tests. Squire is designed to inject mock dependencies by creating an isolated RequireJS context. A side effect of this is that the 'foo' library will be reload each time you call injector.require(), resetting the state of your library. The only downside is that your tests will need to be asynchronous.

    // testfoo.js
    define(['Squire', 'foo'], function (Squire, foo) {
    
     'use strict';
    
      QUnit.start();
    
      QUnit.module('foo', {
        setup: function () {
        },
        teardown: function () {
        }
      });
    
      QUnit.test('Testing foo counter in main context.', 2, function (assert) {
        assert.equal(foo.doStuff(), 1); // this will work
        assert.equal(foo.doStuff(), 2); // this should work also.
      });
    
      QUnit.test('Testing foo counter in context created by Squire.', 1, function (assert) {
        var done = assert.async(),
          injector = new Squire();
    
        injector.require([
          'foo'
        ], function (foo) {
          assert.equal(foo.doStuff(), 1); // this will work.
          done();
        });
    
      });
    
    });
    

    I've posted a sample project here: qunit-squirejs