【问题标题】:Reset module in unit tests在单元测试中重置模块
【发布时间】:2016-01-19 23:00:02
【问题描述】:

我有一个使用以下模式创建的 requirejs 模块:

// foo.js
define(function(){

    var x = 0;

    function doStuff(){
        return ++x;
    }

    return { doStuff: doStuff };

});

还有一个看起来像这样的 QUnit 测试:

// 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;
});

如何为每次测试重置foo?

我想保留 foo 一个显示模块,即不将其转换为具有更改原型的构造函数。

我试过var foo = require('foo');,但由于 requirejs 是基于 AMD 的,它会抱怨加载顺序错误。

【问题讨论】:

    标签: javascript unit-testing requirejs qunit


    【解决方案1】:

    我建议查看SquireJS 为您的测试创建一个独立的上下文。 Squire 旨在通过创建隔离的 RequireJS 上下文来注入模拟依赖项。这样做的副作用是每次调用 injector.require() 时都会重新加载“foo”库,从而重置库的状态。唯一的缺点是您的测试需要异步。

    // 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();
        });
    
      });
    
    });
    

    我在这里发布了一个示例项目:qunit-squirejs

    【讨论】:

    • 谢谢,我会调查的。您能否详细说明“...您的测试需要异步”的缺点。您是否暗示测试不能相互依赖?如果是这样,我会说这是一件好事,因为他们不应该这样做。
    • 当一个模块在初始化过程中调用另一个模块时很有帮助,例如bar.js -> 定义(['foo'],函数(foo){ foo.doStuff(); })。如果您希望 foo.doStuff() 返回某个结果或抛出异常,您可以使用 Squire 注入 foo.js 的模拟,例如 injector.mock('foo', fooMock).require(['bar '], 函数(条形){....})
    【解决方案2】:

    虽然这当然不是最干净的方法,但通过将函数保存为字符串,并在每次测试之前重新创建函数,您可以达到相同的效果。

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

    【讨论】:

    • 虽然这个代码片段可能会回答这个问题,但如果你能解释它是如何解决问题的,它对未来的读者会更有价值。
    • 感谢您的反馈。我希望其他人能给出比这更好的答案……哈哈,不过我会更新它
    猜你喜欢
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 2016-02-23
    相关资源
    最近更新 更多