如何:模拟模块依赖项

时间:2015-11-11 12:44:02

标签: angularjs unit-testing

在这个上撕掉我的头发。

我有以下模块/控制器我想测试

java.lang.Boolean

模块monitor.wunderTable包含一个应该在控制器之前加载的指令,但我想要测试的控制器实际上并不依赖于monitor.wunderTable。但是monitor.wunderTable确实有很多其他的依赖....

我的测试文件:

angular
    .module('monitor.tableLord.controller', ['monitor.wunderTable'])
    .controller('TableLordController', TableLordController);

    TableLordController.$inject = ['$scope', 'historyState'];
    function TableLordController($scope, historyState) {
        ....some code....
    }

出于某种原因(我认为这不可能),我的模拟版本的monitor.wunderTable干扰了我对这个模块的测试。此模块中定义的控制器的每个测试现在都失败:“Argument'WunderTableController'不是函数,未定义”。

我认为它是相关的,这是我对monitor.wunderTable的定义:

describe('TableLordController', function() {
    var $scope, historyState;

    beforeEach(function() {
        angular.module('monitor.wunderTable', []);
        module('monitor.tableLord.controller');
    });

    beforeEach(angular.mock.inject(function($rootScope, $controller) {
            $scope = $rootScope.$new();
            $controller('TableLordController', {$scope: $scope, historyState: {}});
    }));

    it('loads', function() {
        $scope.$digest();
    });
});

编辑:建议我删除模块依赖项(因为它不是严格需要的)的帖子将不被接受为正确答案(并且可能是下注)。

1 个答案:

答案 0 :(得分:2)

您的困惑来自误解模块在Angular中的工作方式。模块are stored inside angular。一旦它们被覆盖,它们将被覆盖当前的测试运行,而不是当前的规范。 ngMock不支持模块模拟(它需要在Angular核心中进行一些实质性的更改),而beforeEach对任何事都没有帮助。

除非您想在单独的运行中运行测试套件,否则解决方案是在模拟之前备份模块。在某些情况下,angular.extendangular.copy无法正确处理复杂对象。 Object.assignjQuery.extendnode-extend可能是更好的候选人。在extend的情况下,如果需要,也可以使用深拷贝。

所以在一个测试套件中它是

var moduleBackup = angular.module('monitor.wunderTable');
angular.module('monitor.wunderTable', []);

describe('TableLordController', function() {
    ...

在另一个

Object.assign(angular.module('monitor.wunderTable'), moduleBackup);

describe('WunderTableController', function() {
    ...

TDD的好处在于它清楚地表明了应用程序设计中的缺陷,并教导开发人员立即以无情的方式编写测试友好的代码。模块依赖性意味着模块内的组件依赖于另一个组件。如果它们没有或者它们耦合得太紧,这可以被认为是潜在的缺陷和重构的主题。

解决方案是破解并且容易破坏的事实使其不适合进行测试。

TL; DR:是的,您必须删除模块依赖项。