【问题标题】:How to mock dependencies for ES6 unit tests?如何模拟 ES6 单元测试的依赖关系?
【发布时间】: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 的缺点是,在调试测试时,在浏览器中运行的代码看起来与原始代码不同(默认情况下)。因此,可能的错误更难识别。这里的帮助是:


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 模块进行单元测试?有人尝试将玩笑与业力结合起来吗?

相关内容:

【问题讨论】:

    标签: unit-testing debugging ecmascript-6 mocking karma-runner


    【解决方案1】:

    我从 karma 切换到 jest,这是一个有效的演示项目:

    https://github.com/stefaneidelloth/testDemoES6Jest

    工作流程仍然基于转译器 (babel),但它发生在后台,不会真正影响开发体验。


    模拟某些 ES6 模块的示例测试代码:

    import Qux from './../src/qux.js';
    
    jest.mock('./../src/baa.js', () => {
        return class BaaMock {
            constructor(name){
                this.name = name;
            }
    
            baaMethod(){
                return 'baaMockedMethod';
            }
        }   
    });
    
    describe('Qux', function(){
    
        var sut;        
    
        beforeEach(function(){                  
            sut = new Qux('qux');
        });
    
        it('quxMethod', function(){         
            expect(sut.quxMethod()).toEqual('quxMethod');
        }); 
    
        it('baaMethod', function(){         
            expect(sut.baaMethod()).toEqual('baaMockedMethod');
        }); 
    
        it('overridableMethod', function(){         
            expect(sut.overridableMethod()).toEqual('qux');
        });         
    
    }); 
    

    示例 package.json(为测试命令启用了代码覆盖率):

    {
      "name": "testDemoES6Jest",
      "version": "1.0.0",
      "main": "index.js",
      "repository": "https://github.com/stefaneidelloth/testDemoES6Jest.git",
      "author": "Stefan Eidelloth <matameko@posteo.de>",
      "license": "MIT",
      "dependencies": {},
      "devDependencies": {
        "@babel/core": "^7.5.5",
        "@babel/preset-env": "^7.5.5",
        "babel-jest": "^24.8.0",
        "jest": "^24.8.0",
        "jest-cli": "^24.8.0",
        "requirejs": "2.3.6"
      },
      "scripts": {
        "test": "jest --coverage --collectCoverageFrom src/**/*.js ",
        "debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --watch --runInBand"
      }
    }
    

    调试several options,例如:

    a) VisualStudioCode,连同 Jest 插件

    (Debug=>安装额外的调试器=> Jest ("Use Facebook's Jest with Pleasure", https://github.com/jest-community/vscode-jest)

    示例调试配置launch.json:

    {
        // Use IntelliSense to learn about possible attributes.
        // Hover to view descriptions of existing attributes.
        // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
        "version": "0.2.0",
        "configurations": [
    
            {
                "type": "node",
                "request": "launch",
                "name": "Jest Tests",
                "program": "${workspaceRoot}\\node_modules\\jest\\bin\\jest.js",
                "args": [
                    "-i"
                ],           
                "internalConsoleOptions": "openOnSessionStart"           
            }
        ]
    }
    

    b) 谷歌浏览器

    • 运行以下控制台命令:

      节点 --inspect-brk ./node_modules/jest/bin/jest.js

    (可以在您的 packages.json 中的脚本下另存为别名:{"debug": ... 并使用 npm run-script debug 运行)

    • 打开Chrome浏览器并输入地址

      chrome://检查

    • 点击Open Dedicated DevTools for Node

    • 将您的项目目录拖放到开发工具以允许文件访问(只需要一次)

    • 打开要调试的文件并设置断点

    • 在开发工具中单击继续以继续到您想要的断点

    另见

    c) 网络风暴

    https://blog.jetbrains.com/webstorm/2018/10/testing-with-jest-in-webstorm/


    对于浏览器中的测试,另请参阅

    【讨论】:

      猜你喜欢
      • 2015-02-04
      • 2023-03-13
      • 1970-01-01
      • 2016-02-19
      • 2016-08-02
      • 2019-12-08
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      相关资源
      最近更新 更多