如何在单元测试之间重置 requirejs 模块
how to reset a requirejs module between unit tests
我有一个 JavaScript 项目,我想观察 TDD 方法。我为此选择了 karma 框架和 requirejs 库,并遵循了 karma 文档 here.
中演示的示例
有一个单元测试文件的例子,它是:
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);
});
});
});
这种方法的主要问题是没有办法为每次测试清除App模块。因此,如果在一个 it
调用中 App 发生了一些变化(如闭包变量变化等),那么它们会影响其他 it
调用。
有人可以对此提出建议吗?这些都是如此流行的工具,我不敢相信没有人 运行 遇到这种情况。
所以,为了概括这个问题,我想就这些更具体的问题寻求答案:
- 有什么方法可以在 requirejs 中 "reset"(清除)模块吗? (其实,我想没有这样的方法,除非重新加载所有模块)
- 对于 运行 karma 和 requirejs 是否有更好的方法,以便模块上没有任何其他测试(
it
函数调用)的遗留(副作用)?
- is there any way to "reset" (clear) module in requirejs?
您可以使用 requirejs.undef()
,但文档提到了一些陷阱。据我所知,没有调用可以用来表示 "unload this module and everything it depends on",这在复杂的应用程序中可能是需要的。
- is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?
更好的方法是设计您的应用程序,使状态与您实例化的对象相关联,而不是与 模块 本身相关联。这就是我在我的一个大型应用程序的测试套件中所做的。 beforeEach
挂钩重置需要重置的内容并为每个测试重新实例化应用程序。
在 Google 的帮助下,我找到了解决方法。我不能说它是理想的,但它至少可以工作,并且在每个测试中,一个必需的模块处于 原始 状态。
首先,需要有这样的 main.js
测试文件,它几乎与 docs 中的相同,只是测试未定义为模块且未作为依赖项包含在内:
require.config({file
baseUrl: '/base',
paths: {},
shim: {},
deps: [],
callback: window.__karma__.start
});
在主要的karma配置中必须存在这个(需要调整自己的路径)
files: [
{pattern: 'src/**/*.js', included: false},
'tests/unit/**/*.js'
],
并且在测试本身中,我们利用 jasmine 异步测试功能和 requirejs.undef 方法 "clearing"模块(这 将重置加载程序的内部状态以忘记模块的先前定义 ,如 docs 中所述)。
这个方法有一个含义,它不会重置其他模块,这些模块已经加载并依赖于重置模块,但这应该不是问题,如果以正确的方式编写他的测试,那就是他只测试一个模块(可能是一些父模块,子模块从中继承了一些行为),因此不难 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))
})
})
我已经检查过了,在 it
调用之间对模块的更改不会持续存在,所以我想,使用这种方法是安全的。
谢谢大家的帮助,如果有人有更好的方法,请在这里回答。
我有一个 JavaScript 项目,我想观察 TDD 方法。我为此选择了 karma 框架和 requirejs 库,并遵循了 karma 文档 here.
中演示的示例有一个单元测试文件的例子,它是:
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);
});
});
});
这种方法的主要问题是没有办法为每次测试清除App模块。因此,如果在一个 it
调用中 App 发生了一些变化(如闭包变量变化等),那么它们会影响其他 it
调用。
有人可以对此提出建议吗?这些都是如此流行的工具,我不敢相信没有人 运行 遇到这种情况。
所以,为了概括这个问题,我想就这些更具体的问题寻求答案:
- 有什么方法可以在 requirejs 中 "reset"(清除)模块吗? (其实,我想没有这样的方法,除非重新加载所有模块)
- 对于 运行 karma 和 requirejs 是否有更好的方法,以便模块上没有任何其他测试(
it
函数调用)的遗留(副作用)?
- is there any way to "reset" (clear) module in requirejs?
您可以使用 requirejs.undef()
,但文档提到了一些陷阱。据我所知,没有调用可以用来表示 "unload this module and everything it depends on",这在复杂的应用程序中可能是需要的。
- is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?
更好的方法是设计您的应用程序,使状态与您实例化的对象相关联,而不是与 模块 本身相关联。这就是我在我的一个大型应用程序的测试套件中所做的。 beforeEach
挂钩重置需要重置的内容并为每个测试重新实例化应用程序。
在 Google 的帮助下,我找到了解决方法。我不能说它是理想的,但它至少可以工作,并且在每个测试中,一个必需的模块处于 原始 状态。
首先,需要有这样的 main.js
测试文件,它几乎与 docs 中的相同,只是测试未定义为模块且未作为依赖项包含在内:
require.config({file
baseUrl: '/base',
paths: {},
shim: {},
deps: [],
callback: window.__karma__.start
});
在主要的karma配置中必须存在这个(需要调整自己的路径)
files: [
{pattern: 'src/**/*.js', included: false},
'tests/unit/**/*.js'
],
并且在测试本身中,我们利用 jasmine 异步测试功能和 requirejs.undef 方法 "clearing"模块(这 将重置加载程序的内部状态以忘记模块的先前定义 ,如 docs 中所述)。
这个方法有一个含义,它不会重置其他模块,这些模块已经加载并依赖于重置模块,但这应该不是问题,如果以正确的方式编写他的测试,那就是他只测试一个模块(可能是一些父模块,子模块从中继承了一些行为),因此不难 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))
})
})
我已经检查过了,在 it
调用之间对模块的更改不会持续存在,所以我想,使用这种方法是安全的。
谢谢大家的帮助,如果有人有更好的方法,请在这里回答。