如何在单元测试之间重置requirejs模块

use*_*860 6 javascript unit-testing requirejs karma-runner

我有一个JavaScript项目,我想观察TDD方法.我选择这样做的业力框架和requirejs库,并遵循业力的文档证明的例子在这里.

有一个单元测试文件的示例,它是:

define(['app', 'jquery', 'underscore'], function(App, $, _) {

    describe('just checking', function() {

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});
Run Code Online (Sandbox Code Playgroud)

这种方法的主要问题是无法清除每个测试的App模块.因此,如果在一次it调用中App中有一些更改(如关闭变量更改等),则它们可能会影响其他it调用.

有人可以就此提出建议吗?这些都是如此受欢迎的工具,我无法相信没有人遇到过这样的情况.

因此,为了概括这个问题,我想问一下这些更具体的答案:

  • 有没有办法在requirejs中"重置"(清除)模块?(实际上,我认为没有这样的方法,除了再次重新加载所有模块)
  • 是否有更好的方法来运行karma和requirejs,这样模块就没有任何其他测试(it函数调用)的遗留(副作用)?

use*_*860 3

在谷歌的帮助下,我找到了解决方案。我不能说它是理想的,但它至少可以工作,并且在每次测试中所需的模块都处于原始状态。

首先,需要有这样的测试文件,它与文档main.js中的几乎相同,除了测试没有定义为模块并且不包含为依赖项:

require.config({file
    baseUrl: '/base',
    paths: {},
    shim: {},
    deps: [],
    callback: window.__karma__.start
});
Run Code Online (Sandbox Code Playgroud)

在主业力配置中必须存在这一点(需要调整自己的路径)

files: [
    {pattern: 'src/**/*.js', included: false},
    'tests/unit/**/*.js'
],
Run Code Online (Sandbox Code Playgroud)

在测试本身中,我们利用jasmine异步测试功能和requirejs.undef方法来“清除”模块(这将重置加载程序的内部状态以忘记模块的先前定义,如文档中所述)。

此方法有一个含义,即它不会重置其他已加载并依赖于重置模块的模块,但这应该不是问题,如果一个人以正确的方式编写他的测试,即他只测试一个模块(并且可能是一些父模块,子模块从中继承一些行为),因此undef同时使用多个模块应该不难。

describe('Some/Module tests', function() {
    'use strict'
    var M

    beforeEach(function(done) {
        requirejs.undef('src/Some/GParentModule')
        requirejs.undef('src/Some/ParentModule')
        requirejs.undef('src/Some/Module')
        require(['src/Some/Module'], function(m) {
            M = m
            done()
        })
    })

    it('some description', function() {
        var i = 0

        for (var prop in M) {
            i++
        }
        expect(i).toEqual(1)
        expect(prop).toEqual('init')
        expect(M.init).toEqual(jasmine.any(Function))
    })
})
Run Code Online (Sandbox Code Playgroud)

我已经检查过这一点,在it调用之间对模块的更改不会持续存在,所以我想,使用这种方法是安全的。

谢谢大家的帮助,如果有人有更好的方法,请在这里回答。