2015-06-25 5 views
1

Таким образом, в принципе нет информации о том, как опустить блоки конфигурации/запуска/поставщика на модули, не выполняя приказ об упорядочении загрузки файлов для модульных тестов. Предположим следующее:Поистине насмешливые провайдеры

// dependency chain for providers: 
// aaa <- bbb <- ccc 


angular.module('module0').provider('bbb', [ 
    'aaaProvider', 
    function (aaaProvider) { 
    // aaaProvider definition 
    ... 
    }); 

angular.module('module1').provider('ccc', [ 
    'bbbProvider', 
    function (bbbProvider) { 
    // bbbProvider definition 
    ... 
    }); 

angular.module('module1').controller('controller', [ 
    function() { 
    // controller definition 
    }]); 

Теперь предположим, что мы пишем модульный тест для controller. Как мы это сделаем?

module('module1'); 
inject(function ($controller, $rootScope) { 
    ... 
}); 

Упс, у нас есть проблема. module('module1') приведет к определению поставщика для ccc, который имеет зависимость от bbb, который имеет зависимость от aaa. Поэтому, если мы не предотвращаем определение провайдера для ccc, запущенного на module1, мы будем запускать код, который не имеет ничего общего с controller, который мы тестируем на модуле.

Мы можем высмеять bbb, используя module(function ($provide) { ... }); обозначение, и таким образом нам не нужно будет загружать module0.

Но это не решает проблему для ccc. У меня нет возможности остановить его.

Вопрос: Есть ли способ, чтобы остановить module1 запуск определения ccc провайдера, который не имеет ничего общего с controller мы модульное тестирование?

Вещей я пытался до сих пор: определение

  • Override в единичном испытании:

    angular.module('module1').provider('ccc', [function() {}]);

ответ

2

Прежде всего, необходимо создать в вашем app.js два модуля

module1internal - этот модуль не будет иметь зависимостей и будет использоваться для все ваших поставщиков приложений

angular.module('module1internal', []); 

module1 - этот модуль зависит от module1internal и будет включать в себя всю другую зависимость, конфигурацию и запуск блок

angular.module('module1', ['module1internal','bbbProvider']); 

в вашем приложении вы должны использовать только внутренний модуль для примера вместо

angular.module('module1').controller('controller', [ 
    function() { 
    // controller definition 
    }]); 

вы должны использовать

angular.module('module1internal').controller('controller', [ 
     function() { 
     // controller definition 
     }]); 

Тесты будут выглядеть следующим образом:

'use strict'; 

describe('Controller: TheController', function() { 

    // mock second level dependencies 
    beforeEach(function() { 
    module('module1internal'); 
    module({ 
     bbb: {} 
    }); 
    }); 

    var TheController, scope, 
    cccMock; 

    // mock injected providers 
    beforeEach(inject(function (_ccc_) { 
    cccMock = mock(_ccc_); 
    })); 


    // Initialise the controller and mock scope 
    beforeEach(inject(function ($controller, $rootScope) { 
    scope = $rootScope.$new(); 
    TheController = $controller('TheController', { 
     $scope: scope 
    }); 

    })); 

    it(' should call ccc functionA on functionThatUsesFunctionA call', function() { 
    TheController.functionThatUsesFunctionA("someValue"); 
    expect(cccMock.functionA).toHaveBeenCalledWith("someValue"); 
    }); 



    //create spy on all provider's methods(mock it) 
    function mock(angularServiceToMock) { 

    for (var i = 0; i < Object.getOwnPropertyNames(angularServiceToMock).length; i++) { 
     spyOn(angularServiceToMock, Object.getOwnPropertyNames(angularServiceToMock)[i]); 
    } 
    return angularServiceToMock; 
    } 

}); 
+0

Это жизнеспособное решение, хотя это означает, что много рефакторинга для меня (это огромное приложение с сотнями контроллеров, директивы, провайдеры работают блоки и т.д.) – mostruash

+0

Это лучший совет для новых проектов. –

+0

Хм, так прошло некоторое время с момента ответа на этот вопрос. С помощью этого подхода, как вы можете тестировать отдельные поставщики внутри 'module1internal', не запуская других поставщиков в модуле? – mostruash