I have a case to unit test a custom Angular directive myApp and have set up the necessary karma and jasmine config.
In this test case I've tried to mock and stub the dependency module of myApp, which is the service - services.FuzzAPI.
As I don't have access to the services.FuzzAPI file to mock it using sinon.
Following the Angular and Jasmine docs I setup up my spec file in the .spec file and following this similar SO answer
- In first beforeEach created a mock of the depedency accroding to this guide
and registered the
myAppmodules to test usingangular.mock.module. - Then in the second beforeEach used the $injector to pass that mocked FuzzAPI for $compile step of
myAppdirective.
But even after mocking the dependency I get an $injector:modulerr telling me that the services.FuzzAPI is not available.
Which tells me soemthing is a miss with the registration of the services.FuzzAPI dependency:
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
Question:
How can you mock a directive depedency in a Jasmine unit test?
Looking at the code I can see that this error is being thrown on line beforeEach(inject(function($rootScope, _$compile_, $injector) {
as the console.log inside the inject beforeEach isn't tirggered before the error is thrown.
Gist of directive and test spec:
// 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
};
}
})();
//my-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
}));
});