如何模拟ES6单元测试的依赖关系?

时间:2019-08-06 15:10:12

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

我有一些要转换为ES6的ES5示例项目:

https://github.com/stefaneidelloth/testDemoES5

https://github.com/stefaneidelloth/testDemoES6

示例包括从类Qux继承的类Baa

在测试Qux时,我想模拟Baa

对于 ES5 ,我使用 Squire.js 模拟AMD模块依赖关系,并且单元测试工作正常

不幸的是,我找不到直接支持ES6(=“ ESMAScript 2015 Language”,ES2015)模块的测试框架。我们现在有2019年,ES2015仍然没有单元测试?我已经花了很多时间尝试使这些测试正常工作……并且我的印象是我的方法缺少一些东西。

由于找不到直接对ES6测试的支持,因此我尝试坚持使用业力,并使用Webpack将ES6模块代码转换为ES5 AMD模块进行测试


首先让我们考虑将业力与已转换为AMD模块的requirejs和ES6代码结合使用。

A。。如果我尝试使用 Squire 模拟翻译的类Baa(模块'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模块,与我的业力+ 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;
    }       

}); 

=>我收到错误消息

  

未捕获的ReferenceError:模块未定义。

我也尝试过mock-loader,但没有成功。


C。。我尝试不使用AMD模块,而是将CommonJs模块用作Webpack编译的目标。但是,我没有设法同时使用commonjs预处理器和karma的and webpack预处理器。


D。。我尝试将System.js而不是require.js和Webpack与Karma一起使用。但是,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模块,但似乎没有一种方法能很好地解决问题。

=> 如果我应该坚持业力,我该如何调整我的测试qux.test.js示例代码(可能还有我的配置文件)以正确模拟类{{1} }?

=> 是否可以告诉webpack 将翻译后的模块分开,以便我可以轻松地使用Squire.js注入依赖项?

=> 在浏览器中进行单元测试ES6模块是否有更好的最新工作流程/框架?有人试图用业力来开玩笑吗?

相关内容:

1 个答案:

答案 0 :(得分:0)

我从业力切换到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插件

(调试=>安装其他调试器=>笑话(“将Facebook的笑话高兴地使用”,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)谷歌浏览器

  • 运行以下控制台命令:
      

    node --inspect-brk ./node_modules/jest/bin/jest.js

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

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

      

    chrome:// inspect

  • 单击打开Node专用DevTools

  • 将项目目录拖放到dev工具中以允许文件访问(仅需要一次)

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

  • 在开发工具中单击继续以继续到所需的断点

另请参见

c)网络风暴

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


有关浏览器中的测试,请参见 * https://github.com/smooth-code/jest-puppeteer * https://developers.google.com/web/tools/puppeteer/get-started

相关问题