我有一个单元测试自定义Angular指令myApp
的情况,并设置了必要的业力和茉莉配置。
在这个测试用例中,我试图模拟并存根myApp
的依赖模块,即服务 - services.FuzzAPI
。
因为我无法访问services.FuzzAPI文件来使用sinon来模拟它。
按照Angular和Jasmine文档,我在.spec
文件中设置了我的规范文件并遵循此similar SO answer
myApp
注册angular.mock.module
模块进行测试。myApp
指令的$ compile步骤。 但即使在模拟了依赖项后,我得到一个$injector:modulerr
告诉我services.FuzzAPI不可用。
这告诉我soemthing是services.FuzzAPI
依赖注册的错过:
LOG LOG: 'before mock'
LOG LOG: 'after mock'
Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:modulerr] Failed to instantiate module services.FuzzAPI due to:
Error: [$injector:nomod] Module 'services.FuzzAPI' is not available! You either misspelled the module name or forgot to load it
问题:
如何在Jasmine单元测试中模拟指令依赖?
查看代码,我可以看到此错误正在行beforeEach(inject(function($rootScope, _$compile_, $injector) {
上
因为在注入错误之前,注入beforeEach
内的console.log没有被修改。
指令和测试规范的要点:
// my-app.js
(function() {
var component = {
id: "myApp",
name: "My App",
templateUrl: localStorage.getItem("baseURL") + "my-app/my-app.html"
};
component.ui = angular.module("myApp", ["services.FuzzAPI"]);
component.ui.directive("myApp", widgetComponent);
function widgetComponent(FuzzAPI) {
// main widget container
function widgetContainer(scope, element, params) {
var api = new FuzzAPI(params);
scope.greeting = "Hello World";
var setGreeting = function(message){
scope.greeting = message;
};
api.onDataEvent("onFuzzEvent", function(data) {
scope.greeting = data;
});
element.on("$destroy", function() {
api.unregister();
scope.$destroy();
});
}
return {
scope: {},
replace: true,
link: widgetContainer,
templateUrl: component.templateUrl
};
}
})();
//我-app.spec.js
describe("myApp", function() {
var $scope, $compile, $provide, $injector, element, fuzzAPIMock, FuzzAPIProvider;
beforeEach(function(){
//mock service FuzzAPI via service provider
fuzzAPIMock = {
greeting : "123",
initializeCurrentItem : function () {
return true;
}
};
console.log("before mock");
//register module and mock dependency
angular.mock.module(function($provide) {
$provide.value('services.FuzzAPI', fuzzAPIMock);
});
angular.mock.module("myApp");
console.log("after mock");
});
beforeEach(inject(function($rootScope, _$compile_, $injector) {
console.log("in inject..");
FuzzAPIProvider = $injector.get('services.FuzzAPI');
$scope = $rootScope.$new(), //create instance of rootScope
$compile = _$compile_;
console.log("in inject before compile..");
element = $compile("<my-app></my-app>")($scope); // compile attaches directives to HTML template
console.log("in inject after compile..");
$scope.$digest(); //loop through DOM watchers, check values and trigger listeners
}));
});
答案 0 :(得分:2)
错误:[$ injector:nomod]模块'services.FuzzAPI'不可用!您要么错误拼写了模块名称,要么忘记加载它
表示应该模拟services.FuzzAPI
模块,而不是服务。根据提供的代码,服务名称为FuzzAPI
,应使用构造函数进行模拟,而不是对象。
为了使丢失的模块不会导致错误,它应该是存根的。它可以在顶级describe
块中存根一次:
beforeAll(() => {
angular.module('services.FuzzAPI', []);
});
无法恢复存根模块(至少没有黑客攻击),但如果不在测试中显示真实模块,则不会出现问题。
然后可以照常模拟服务。如果是FuzzAPI
:,则应为
fuzzAPIMock = jasmine.createSpy('').and.returnValue({
greeting : "123",
initializeCurrentItem : jasmine.createSpy('').and.returnValue(true)
});
angular.mock.module(function($provide) {
$provide.value('FuzzAPI', fuzzAPIMock);
});
最好使用Jasmine间谍作为模拟/存根函数。