An issue arises when attempting to perform AngularJS Karma Unit Testing on a service.
The service includes a method like the one below:
service.getIntersectingElements = function (element, elements) {
var deferred = $q.defer();
var tolerance = 20;
var intersectingElements = [];
$timeout(function () {
for (var i = 0; i < elements.length; i++) {
if (element.$$hashKey != elements[i].$$hashKey)
if (service.checkIntersection(element.Location, elements[i].Location, tolerance))
intersectingElements.push(elements[i]);
}
if (intersectingElements.length > 0)
deferred.resolve(intersectingElements);
else
deferred.reject();
});
return deferred.promise;
};
This service method functions properly when called by the controller. However, the goal is to test this method, which returns a promise that resolves later. The intent is to retrieve and compare the resolved value in the unit test.
A karma test was written as follows:
it('should get the intersecting elements', function () {
var element = {Id: 1, Name: 'Water', Location: {x: 200, y: 200}};
var elements = [{Id: 2, Name: 'Fire', Location: {x: 200, y: 200}}];
service.getIntersectingElements(element, elements).then(function (result) {
expect(result).toEqual([{Id: 2, Name: 'Fire', Location: {x: 200, y: 200}}]);
});
});
When calling the service method exactly as done in the controller, the test ends with a "done" statement, indicating success. However, changing the expectation line to:
expect(result).toEqual("Test");
The test still passes, rather than failing as expected.
Efforts have been made to inject $rootScope
and call $rootScope.$digest();
after invoking the service method, but these actions have not had any effect.
Therefore, the question remains: how can one effectively test the promise returned by the service method and accurately compare the resolved value passed to the then() function in the Karma unit test?
Edit:
Attempts were made using $timeout.flush();
and $rootScope.$digest();
following the service method call.
The services were injected in the following manner:
var service;
var $timeout;
var $rootScope;
beforeEach(module('app'));
beforeEach(module('app.services'));
beforeEach(angular.mock.inject(function (intersectService, _$timeout_, _$rootScope_) {
service = intersectService;
$timeout = _$timeout_;
$rootScope = _$rootScope_;
}));