我在这里有一个有点复杂的场景,我会尽力解释它,抱歉,如果它感到困惑。
说,我有一个设计好的提供者坐在名为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's 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
服务)
答案 0 :(得分:0)
查找注入myActionFn
的内容很简单,只需要检查函数的$inject
属性即可。
下一步是简单地调用函数,将需要注入的函数传递给它。
在这种情况下使用Function.prototype.apply
无济于事,因为我们需要使用angular的$ injector。使用angular.injector()
创建实例也不起作用,因为我们需要使用正确的注入器实例。
诀窍是使用angular.mock.injector
来获取当前的注入器实例。
所以我们的invoke
函数应如下所示:
self.invoke = (actionName) {
// instead of array it's probably better to use an object map for `actions`
let action = actions[actionName];
inject(($injector)=> {
$injector.invoke(action.$fn);
})
};