【发布时间】:2019-12-14 04:28:26
【问题描述】:
我有一些 ES5 示例项目,我想将其转换为 ES6:
https://github.com/stefaneidelloth/testDemoES5
https://github.com/stefaneidelloth/testDemoES6
示例包括一个类Qux,它继承自一个类Baa。
在测试Qux 时,我想模拟Baa。
对于 ES5,我使用 Squire.js 来模拟 AMD 模块依赖项,并且单元测试工作正常。
不幸的是,我找不到直接支持 ES6 (="ECMAScript 2015 Language", ES2015) 模块的测试框架。我们现在已经 2020 年了,仍然没有 ES2015 的单元测试?我已经花了很多时间试图让这些测试正常工作......而且我的印象是我的方法缺少一些东西。
由于找不到对 ES6 测试的直接支持,我尝试坚持 karma 并使用 webpack 将 ES6 模块代码转换为 ES5 AMD 模块进行测试。
让我们首先考虑将 karma 与 requirejs 和已翻译为 AMD 模块的 ES6 代码结合使用。
A. 如果我尝试使用 Squire 模拟已翻译的类 Baa (module 'src/baa') ...那将不再起作用。 Webpack 将所有依赖项放在一个文件中,当使用 'src/qux' 时,我注入的 'src/baa' 不被考虑。
qux.test.js:
define([
'squire'
], function (
Squire
) {
describe('Qux', function(){
var sut;
beforeEach(function(done){
var injector = new Squire();
injector.mock('src/baa', createBaaMock());
injector.require([
'src/qux'
], function(
quxModule
){
var Qux = quxModule.default;
sut = new Qux('qux');
done();
});
});
it('quxMethod', function(){
expect(sut.quxMethod()).toEqual('quxMethod');
});
it('baaMethod', function(){
expect(sut.baaMethod()).toEqual('baaMockedMethod');
});
it('overridableMethod', function(){
expect(sut.overridableMethod()).toEqual('qux');
});
function createBaaMock(){
var BaaMock = function (name) {
this.name = name;
};
BaaMock.prototype.baaMethod = function () {
return 'baaMockedMethod';
}
var moduleMock = {
default: BaaMock
}
return moduleMock;
}
});
});
=> 我得到了错误
预期“baaMethod”等于“baaMockedMethod”。
更多关于调试的信息.... 转换为 ES5 的缺点是,在调试测试时,在浏览器中运行的代码看起来与原始代码不同(默认情况下)。因此,可能的错误更难识别。这里的帮助是:
使用 webpack 模式“开发”而不是“生产”以避免缩小
启用devtool option of webpack to enable source mapping。这样,在调试时,原始代码也会显示在浏览器中。
B. 我尝试使用 inject-loader,它是 Squire.js 的替代品,它了解 webpack: https://github.com/LeanKit-Labs/inject-loader
但是,这似乎是一个 CommonJs 模块,与我的 karma + requirejs 项目不兼容:
qux.test.js:
describe('Qux', function(){
var sut;
beforeEach(function(done){
require(['inject!src/qux'],function(ModuleInjector){
var quxModule = ModuleInjector({
'src/baa': crateBaaMock()
});
var Qux = quxModule.default;
sut = new Qux('qux');
done();
});
});
it('quxMethod', function(){
expect(sut.quxMethod()).toEqual('quxMethod');
});
it('baaMethod', function(){
expect(sut.baaMethod()).toEqual('baaMockedMethod');
});
it('overridableMethod', function(){
expect(sut.overridableMethod()).toEqual('qux');
});
function createBaaMock(){
var BaaMock = function (name) {
this.name = name;
};
BaaMock.prototype.baaMethod = function () {
return 'baaMockedMethod';
}
var moduleMock = {
default: BaaMock
}
return moduleMock;
}
});
=> 我得到了错误
Uncaught ReferenceError: module is not defined.
我也尝试了mock-loader,但没有成功。
C. 我尝试不使用 AMD 模块,而是使用 CommonJs 模块作为 webpack 编译的目标。但是,我没有设法将 karma 的 commonjs 预处理器和 webpack 预处理器一起使用。
D. 我尝试使用 system.js 而不是 require.js 和带有 Karma 的 webpack。但是,karma-system.js 依赖于一个非常旧的 system.js 版本(0.19.47),我没有让它工作。
E. 在对related and old SO question 的回答中,有人建议使用“import * as obj”样式以模块形式导入类,然后监视默认导出 模拟课程。
但是,如果多个测试使用该“修改后的模块”(无法重新定义属性“默认”),这可能会导致问题。
由于webpack没有动态加载依赖,下面的测试失败:
define([
'src/baa',
'src/qux'
],function(
baaModule,
quxModule
){
describe('Qux', function(){
var sut;
beforeEach(function(done){
baaModule.default = createBaaMock();
var Qux = quxModule.default;
sut = new Qux('qux');
done();
});
it('quxMethod', function(){
expect(sut.quxMethod()).toEqual('quxMethod');
});
it('baaMethod', function(){
expect(sut.baaMethod()).toEqual('baaMockedMethod');
});
it('overridableMethod', function(){
expect(sut.overridableMethod()).toEqual('qux');
});
function createBaaMock(){
var BaaMock = function (name) {
this.name = name;
};
BaaMock.prototype.baaMethod = function () {
return 'baaMockedMethod';
}
var moduleMock = {
default: BaaMock
}
return moduleMock;
}
});
});
总而言之,我发现了很多过时和不完整的方法来测试 ES6 模块,但似乎没有一个效果很好。
=> 如果我应该继续使用 karma,我需要如何调整我的测试 qux.test.js 示例代码(可能还有我的配置文件)以正确模拟 Baa 类?
=> 是否可以告诉 webpack 将翻译后的模块分开,以便我可以轻松地使用 Squire.js 注入依赖项?
=> 是否有更好和最新的工作流程/框架用于在浏览器中对 ES6 模块进行单元测试?有人尝试将玩笑与业力结合起来吗?
相关内容:
- https://zirho.github.io/2016/06/06/karma-es6/
- How to mock dependencies for unit tests with ES6 Modules
- https://www.npmjs.com/package/inject-loader
- https://github.com/LeanKit-Labs/amd-inject-loader
- https://jestjs.io/
- https://www.npmjs.com/package/proxyrequire
- ES6 unit testing without compilation
- Webpack: compile folder but keep separate files?
- https://www.reddit.com/r/javascript/comments/44vngp/es6_webpack_unittesting_i_need_help/
- How to disable bundling in Webpack for development?
- Disable Bundling from Webpack
- https://blog.oharagroup.net/mocking-es2015-imports-in-webpack-2-without-loaders-1dec44365989
【问题讨论】:
标签: unit-testing debugging ecmascript-6 mocking karma-runner