如何将requirejs中的模块注入单元测试应用程序?

时间:2014-03-27 22:46:23

标签: javascript unit-testing requirejs jasmine

我有两个模块,ModuleA和ModuleB。 ModuleB依赖于ModuleA。但据我所知,requirejs是一种服务定位器。那么我如何在我的代码中对这种模式进行单元测试。

define('moduleA', function() {
    var ModuleA = function() {
        this.doSomething = function() {
            return true;
        }
    }
    return ModuleA;
});

define('moduleB', ['moduleA'], function(ModuleA) {
    var moduleA = new ModuleA();
    var ModuleB = function() {
        this.doSomethingElse = function() {
            if(moduleA.doSomething()) {
                // do something else and return

            } else {
                // do other things and return
            }
        }
    }

    return ModuleB
});

/*Test for moduleB*/
define('test', ['moduleB', function(ModuleB) {
    describe('', function() {
        var moduleB = new ModuleB();
        expect(moduleB.doSomethingElse()).toBe(true);
    });
});

因为ModuleA会一直初始化。无论如何我可以向ModuleB注入一些模拟并测试吗?我不想使用单身,因为我不确定测试是否会因为无法预料的行为而继续失败。

注意:我只是键入代码,因此它们可能是一些编译错误。

1 个答案:

答案 0 :(得分:2)

此代码模式不可单元测试。我想有人可能想出一种方法来欺骗RequireJS加载不同的模块定义并在测试结束时卸载它,但这样太复杂且容易出错,并且不能解决编码错误的问题

模式是不可测试的,因为在moduleB定义中你正在创建moduleA的新实例(加上ModuleA的加载是"硬编码")。为了使其可测试,您需要注入它。考虑类似的事情:

define('moduleB', function() {
    var ModuleB = function(moduleA) {
        this.__moduleA = moduleA;
        this.doSomethingElse = function() {
            if(this.__moduleA.doSomething()) {
                // do something else and return

            } else {
                // do other things and return
            }
        }
    }

    return ModuleB
});

为了进一步探索这种小型重构,我建议阅读"依赖注入"。跳过像Guice这样的DI工具,只需了解DI想法的核心。

Misko Hevery有几个关于这种OOP模式的有趣帖子,包括如何处理" new"关键字:http://misko.hevery.com/2008/09/10/where-have-all-the-new-operators-gone/

我现在找不到它,但我相信Misko在OOP,继承层次结构(最明显),创建层次结构(谁创建了什么)和依赖层次结构(谁使用谁)方面有好的帖子。这3个层次结构完全不同。通常,如果B类创建A类,它就不应该使用它。 B类的角色似乎是工厂 - 它创造了实例。应该有一些其他类C使用注入的A类实例来执行一些业务逻辑。

作为旁注,因为您已经在使用AMD模块和JS"类"为什么不让你的类/对象外观和行为更像正确的OOP类/对象? Dejavu可以帮助你:http://wojciechszela.com/blog/2014/01/13/object-oriented-programming-in-javascript/