devdropper87
devdropper87

Reputation: 4207

unable to inject module/service for unit test

I am new to TDD and am trying to wire up a test, and have been stuck on it for hours. I keep getting the following error:

[$injector:modulerr] Failed to instantiate module AuthInterceptor due to:
    Error: [$injector:nomod] Module 'AuthInterceptor' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
    http://errors.angularjs.org/1.5.8/$injector/nomod?p0=AuthInterceptor
        at client/test/index.js:8237:13
        at client/test/index.js:10251:18
        at ensure (client/test/index.js:10175:39)
        at module (client/test/index.js:10249:15)
        at client/test/index.js:12786:23
        at forEach (client/test/index.js:8490:21)
        at loadModules (client/test/index.js:12770:6)

Here is my test:

import angular from 'angular';
import serviceModule from './auth.interceptor'

describe('wire.common.services', () => {

  describe('AuthService', () => {
    let AuthService;

    beforeEach(angular.mock.module(serviceModule.name));
    beforeEach(angular.mock.module(($provide) => {
      $provide.factory('$q', () => ({}));
      $provide.factory('$log', () => ({}));
    }));

    beforeEach(angular.mock.inject((_AuthService_) => {
      AuthService = _AuthService_;
    }));

    it('should be a dummy test', () => {
      expect(2).toEqual(2);
    });

  });

});

The actual code I'm testing:

 export default function AuthInterceptor($q, $injector, $log) {
  'ngInject';
  return {
    request(config) {
      let AuthService = $injector.get('AuthService');
      if (!config.bypassAuthorizationHeader) {
        if (AuthService.jwtToken) {
          config.headers.Authorization = `Bearer ${AuthService.jwtToken}`;
        } else {
          $log.warn('Missing JWT', config);
        }
      }
      return config || $q.when(config);
    },
    responseError(rejection) {
      let AuthService = $injector.get('AuthService');
      if (rejection.status === 401) {
        AuthService.backToDAS();
      }
      return $q.reject(rejection);
    }
  };

}

I don't understand why I'm getting this error - I provided all the dependencies for the service and am following what is outlined in the angular documentation. any help is appreciated!

Update, this is the code that I went with:

   import angular from 'angular';
import AuthInterceptor from './auth.interceptor'

describe('Auth interceptor test', () => {

  describe('AuthInterceptor test', () => {
    let $httpBackend, $http, authInterceptor = AuthInterceptor();

    beforeEach(angular.mock.module(($httpProvider, $provide) => {
      $httpProvider.interceptors.push(AuthInterceptor);
      $provide.factory('AuthService', () => ({
        jwtToken: "hello",
        backtoDAS: angular.noop
      }));
    }));

    beforeEach(inject(function($injector) {
      $httpBackend = $injector.get('$httpBackend');
      $http = $injector.get('$http');
    }))


    it('should have a request function', () => {
      let config = {};
      expect(authInterceptor.request).to.be.defined;
      expect(authInterceptor.request).to.be.a('function');

    })

    it('the request function should set authorization headers', (done) => {
      $httpBackend.when('GET', 'http://jsonplaceholder.typicode.com/todos')
        .respond([{
          id: 1,
          title: 'Fake title',
          userId: 1
        }]);
      $http.get('http://jsonplaceholder.typicode.com/todos').then(function(transformedResult) {

        expect(transformedResult.config.headers.Authorization).to.be.defined;
        expect(transformedResult.config.headers.Authorization).to.contain('Bearer')
        done();
      })
      $httpBackend.flush();
    });

    it('should have a responseError function', () => {
      expect(authInterceptor.responseError).to.be.defined;
      expect(authInterceptor.responseError).to.be.a('function');
      //TODO: test return value
      // see that AuthService.backToDAS()
    })

    it('the error function should call backtoDAS', (done) => {
//the URL should be one that gives me a 401
      $httpBackend.when('GET', 'https://wwws.mint.com/overview.event')
        .respond([{
          id: 1,
          title: 'Fake title',
          userId: 1
        }]);
      $http.get('https://wwws.mint.com/overview.event').then(function(transformedResult) {

        console.log(transformedResult);
        done();
      }, function(error){
        console.log(error);
        done();
      })

    });

  })
});

Upvotes: 1

Views: 487

Answers (2)

Estus Flask
Estus Flask

Reputation: 223229

This means that AuthInterceptor Angular module wasn't defined (and by the way, relying on name is unsafe).

AuthInterceptor isn't a module but an injectable function. It can be tested in functional fashion as $http interceptor:

beforeEach(angular.mock.module(($httpProvider) => {
  $httpProvider.interceptors.push(AuthInterceptor);
});

...

it('...', () => {
  $httpBackend.when(...).respond(...);
  $http.get(...).then((interceptedResult) => {
    expect(interceptedResult)...
  });

  $rootScope.$digest();
});

or directly:

it('...', () => {
  let interceptor = $injector.invoke(AuthInterceptor);
  expect(interceptor).toEqual({
    request: jasmine.any(Function),
    requestError: jasmine.any(Function)
  });

  var config = { headers: {} };
  interceptor.request(config);
  expect(config)...
});

Services that produce side effects (AuthService, $log) should be stubbed.

Upvotes: 1

Mustafa Gondalwala
Mustafa Gondalwala

Reputation: 81

This means that ng module is failing to load. :) And this happens while bootstrapping the app and ng module is first in a three element array: ng, ['$provide', function($provide) { ... }] and my own application module. It fails when loading the first one.

I've looked at console and I've copied this error message from it. There's no other error. None.

I hope you clicked that specific link and see that it doesn't give you any specific ideas about it. Unfortunately I've added this GitHub issue after exhausting other resources. I'm currently debugging angular code to get any further.

Upvotes: 0

Related Questions