Reputation: 399
I am trying to write tests for functions that call Async functions from a service and I can not for the life of me figure out how to make Jasmine wait for my Async operations to finish before executing the expect function.
describe('vm.submitLogin', function () {
var $scope;
var $q;
var deferred;
var $controller;
beforeEach(module('myModule'));
beforeEach(inject(function (_$controller_, _$rootScope_, _$q_, LoginService, $httpBackend) {
$q = _$q_;
$scope = _$rootScope_.$new();
$controller = _$controller_;
deferred = _$q_.defer();
spyOn(LoginService, 'login').and.callFake(function () {
return $.Deferred().resolve({success: true, twoFactorRequired: false});
});
$httpBackend.expectGET("/data/I/need/to/mock").respond({"uri": "http://localhost:8081/data/I/need/to/mock.json"});
var vm = $controller('LoginCtrl', { $scope: $scope});
vm.submitLogin();
$scope.$apply();
}));
it('should work, please work...', inject (function ($httpBackend, LoginService) {
expect(something);
}));
});
I have tried to use Jasmine's "done" function, but I cannot figure out how to go about implementing it.
In this example, as soon as
$scope.$apply();
is called, It right away jumps to the expect and fails because the async operations has yet to finish.
Upvotes: 0
Views: 1418
Reputation: 91
Try using $httpBackend.flush() before $scope.$apply() as referred in angular documentation:
The $httpBackend used in production always responds to requests asynchronously. If we preserved this behavior in unit testing, we'd have to create async unit tests, which are hard to write, to follow and to maintain. But neither can the testing mock respond synchronously; that would change the execution of the code under test. For this reason, the mock $httpBackend has a flush() method, which allows the test to explicitly flush pending requests. This preserves the async api of the backend, while allowing the test to execute synchronously.
Upvotes: 1