简体   繁体   English

如何对动态加载JavaScript文件的JavaScript代码进行单元测试?

[英]How to unit test javascript code that dynamically loads javascript files?

Suppose file1.js has a function called doSomething() that dynamically loads file2.js 假设file1.js具有一个名为doS​​omething()的函数,该函数可动态加载file2.js

file2.js sets a global variable window.FILE2_LOADED == true file2.js设置一个全局变量window.FILE2_LOADED == true

How can I write a test like below? 如何编写如下所示的测试?

describe("A Unit Test", function() {
  it("can I load scripts dynamically here?", function() {
    loadScript('base/file2.js');
    waitForDynamicallyLoadedScriptsToLoad_IWishThisFunctionExisted(function(){
        expect(window.FILE2_LOADED).equal(true);
    });
  });

});

UPDATE: I found some solutions (and no-solutions) that I still don't like, but think it's worth documenting. 更新:我找到了一些我仍然不喜欢的解决方案(和无解决方案),但是认为值得记录。

It's on this Github repo (it uses Mocha, not Jasmine) -> https://github.com/tonylampada/AngularJS-Testing-Article 在这个Github存储库上(它使用Mocha,而不是Jasmine)-> https://github.com/tonylampada/AngularJS-Testing-Article

You can run it with grunt test:unit 您可以使用grunt test:unit运行它

The relevant code is in dynamic_load_test.js 相关代码在dynamic_load_test.js中

describe("Unit: dynamic loading scripts", function() {
  it("method 1 works, but using setTimeout and done is still ugly"+
    "also, it may interfere with other tests", function(done) {
    console.log('----------- method 1 -------------');
    window.ACOUNTER = undefined;
    loadScript('base/app/scripts/file2.js');
    setTimeout(function(){
        console.log('m1_2: '+window.ACOUNTER);
        expect(window.ACOUNTER).equal(1);
        done()
    }, 1000)
    console.log('m1_1: '+window.ACOUNTER);
  });

  it("method 2 works too, but I don't wanna have acces to the callback", function() {
    window.ACOUNTER = undefined;
    console.log('----------- method 2 -------------');
    loadScript('base/app/scripts/file2.js', function(){
        console.log('m2_2: '+window.ACOUNTER);
        expect(window.ACOUNTER).equal(1);
    });
    console.log('m2_1: '+window.ACOUNTER);
  });

  it("method 3, doesn't work", function() {
    window.ACOUNTER = undefined;
    console.log('----------- method 3 -------------');
    loadScript('base/app/scripts/file2.js');
    describe("wait for all async to finish", function(){
        it("now it will be loaded", function(){
            console.log('m3_2: '+window.ACOUNTER);
            expect(window.ACOUNTER).equal(1);
        })
    })
    console.log('m3_1: '+window.ACOUNTER);
  });

  it("method 4, use jquery. Callback is never invoked.", function() {
    window.ACOUNTER = undefined;
    console.log('----------- method 4 -------------');
    loadScript('base/app/scripts/file2.js');

    $(document).ajaxStop(function () {
        console.log('m4_2: '+window.ACOUNTER);
        expect(window.ACOUNTER).equal(1);
    });

    console.log('m4_1: '+window.ACOUNTER);
  });

});

Jasmine supports asynchronous tests: https://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support Jasmine支持异步测试: https : //jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support

I would also have the path to the file to be loaded set through an argument to a function, so that you could load some simple mock file instead of an entire (supposedly requiring some other dependencies) script. 我还将通过函数的参数设置要加载文件的路径,以便您可以加载一些简单的模拟文件,而不是整个脚本(可能需要一些其他依赖项)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM