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
myApp
modules to test usingangular.mock.module
. - Then in the second beforeEach used the $injector to pass that mocked FuzzAPI for $compile step of
myApp
directive.
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
}));
});