Johan
Johan

Reputation: 35194

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.

Upvotes: 1

Views: 530

Answers (2)

Belfordz
Belfordz

Reputation: 630

While this certainly isn't the cleanest way about it, by saving the function as a string, and recreating the function before each test, you can accomplish the same effect.

var fooString = foo.toString();
QUnit.testStart(function() { eval('foo = ' + fooString});

Upvotes: -1

Eric Bronnimann
Eric Bronnimann

Reputation: 951

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

Upvotes: 2

Related Questions