Издевательский провайдер

0

У меня здесь несколько сложный сценарий, я попытаюсь изо всех сил объяснить это, извините, если это запутанно.

Скажем, у меня есть надуманный провайдер, который сидит в модуле, точно названном core, назовите его actionProvider, он может регистрировать действия, а затем вызывать их. И я использую его вот так:

 // registering an action in m1 module
 angular.module('m1').config((actionProvider)=> {

     actionProvider.reg('myAction', { $fn: myActionFn });

     myActionFn.$inject = ['$modal'];  

     function myActionFn($modal) {
         $modal.open()    // when action invoked it opens a modal dialog 
     } 
 })


// now somewhere else I invoke that previously registered action 
angular.module('m2').controller('myCtrl', (action)=> {
  action.invoke('myAction');    // and that calls $fn with $modal.open()
})

И это прекрасно работает. Теперь скажем, мне нужно проверить actionProvider в модуле, который не имеет доступа к исходному коду actionProvider. Значит, мне нужно все это издеваться. ОК. Попробуем сделать это:

 angular.module('core', []).provider('action', function() {
     let self = this;
     self.actions = [];

     self.$get = ()=> { return self }; // essential function that every provider has

     // registering action just pushes it into the array of actions,
     // remember this is a fake provider
     self.reg = (action)=> {
        self.actions.push(action) 
     };

     // yet even though it a fake it still needs to be able to invoke actions
     self.invoke = (actionName) {
         // so here I need to find specified action in the array and invoke it
     };
})

Найти правильное действие в self.actions легко. Но как правильно вызвать его $fn? Как сообщить инжектору об обнаружении всех объектов, которые были введены (в случае myAction это будет $modal услуга)

Теги:
unit-testing
mocking

1 ответ

0
Лучший ответ

Поиск того, что вводится в myActionFn, легко, вам просто нужно проверить свойство функции $inject.

Следующий шаг - просто вызвать функцию, передав ей то, что нужно ввести.

Использование Function.prototype.apply в этом случае не поможет, так как нам нужно использовать угловую инъекцию. Создание экземпляра с angular.injector() тоже не сработает, потому что нам нужно использовать правильный экземпляр инжектора.

Фокус в том, чтобы использовать angular.mock.injector для захвата текущего инжектора.

поэтому наша функция invoke должна выглядеть так:

 self.invoke = (actionName) {
     // instead of array it probably better to use an object map for 'actions' 
     let action = actions[actionName]; 

     inject(($injector)=> {
         $injector.invoke(action.$fn);
     })
 };

Ещё вопросы

Сообщество Overcoder
Наверх
Меню