Si-N Si-N - 14 days ago 6
AngularJS Question

Testing route resolve in Angular

I am trying to test some conditions I have in a resolve on a route:


app.js


$routeProvider.when('/:room/login/', {
templateUrl: '/app/login/login.html',
controller: 'LoginCtrl',
resolve: {
auth: ['$q', 'RoomService', 'LoginService', '$location', '$route', function ($q, RoomService, LoginService, $location, $route) {
return RoomService.checkIfRoomExists($route.current.params.room).then(function (success) {
if (success === false) {
$location.path('/notFound');
$location.replace();
return $q.reject();
}
else
{
return LoginService.isUserLoggedIn().then(function (isloggedin) {
if (isloggedin === true) {
var currentPath = $location.path();
$location.path($route.current.params.room);
$location.replace();
return $q.reject();
}
}, function (err) {
return $q.reject(err);
})
}
},
function (err) {
return $q.reject(err);
})
}]
}
})


This is my test:

describe('LoginRoute', function()
{
beforeEach(module('corpusRoom'));

var mockHttp, location, route, rootScope, loginService, roomService;

beforeEach(inject(function($httpBackend, $location, _$route_, $rootScope, LoginService, RoomService){
mockHttp = $httpBackend;
location = $location;
route = _$route_;
rootScope = $rootScope;
spyOn(LoginService, 'isUserLoggedIn');
spyOn(RoomService, 'checkIfRoomExists');
loginService = LoginService;
roomService = RoomService;
}));

it('should check if room exists', function(done)
{
location.path('/anyroom/login');
rootScope.$apply();
expect(roomService.checkIfRoomExists).toHaveBeenCalled();
done();
});
});


But when I run this in Karma it reports this error


TypeError: RoomService.checkIfRoomExists(...).then is not a function
at $routeProvider.when.resolve.auth (public/app/app.js:14:86)


The resolve finds the injected RoomService fine when I run it outside of testing.

Can you see why it can't resolve RoomService?

rrd rrd
Answer

It's the 'then' that is falling down, which you need to mock, so for example:

beforeEach(() => {
  angular.mock.module(services, ($provide) => {
    let RoomService = jasmine.createSpyObj('RoomService', ['checkIfRoomExists']);
    RoomService.checkIfRoomExists.and.returnValue(
      {
        then: () => ({
          catch: () => true
        })
      }
    );
    $provide.value('RoomService', RoomService);
  });
});

Then you won't need to inject RoomService, as $provide will do it for you. Then you Spy should work (I haven't tested this out though) because .then() will be mocked correctly.