0
votes

I'm trying to test a bunch of Angular Services using Karma but it keeps running into errors. Basically I have files called "APIHelper.js" and "Config.js". Within these files, I have created factories namely "APIHelper" and "Config" respectively. Now I have another file "XFactory.js" which defines another factory which actually uses "APIHelper" and "Config".

I've tested the APIHelper and Config factories, I know how to inject simple factory and test it. However, I'm having trouble testing this "XFactory" which has other dependencies.

Here's the code for APIHelper.js:

angular.module('Test').factory('APIHelper', function() {

    appendContext:function(item, context){
        //code here
    }
});

Here's the code for Config.js

angular.module('TesterLib',[]).factory('Configuration', function() {
      //code here
});

Here's the code for XFactory:

'use strict';
angular.module('Test').factory('XFactory', function ($q, $http, APIHelper, Config) {

  function executeRequest(req) {
    .....
    .....
    //make the http call.
    var response = $http(convertedRequest);
    var deffered= $q.defer();

    response.then(function(resp){

      context.response = response;

      //Append the context to the body for easy access
      APIHelper.appendContext(response.body,context);
      deffered.resolve(response);

    },function(resp){
      //Create error
      var error = {message:resp.body,code:resp.statusCode};

      //Append the context to the error object
      APIHelper.appendContext(error,context);
      deffered.reject(error);
    });

      return deffered.promise;
  }

  return executeRequest;

});


    function executeRequest(req) {

        //Convert abstracted request to request's http request
        var convertedRequest = convertHttpRequest(req);

        //create a context to hold raw request and response
        var context = new HttpContext();
        context.request = req;

        //make the http call.
        var response = $http(convertedRequest);
        var deffered= $q.defer();

        response.then(function(resp){

            var response = convertHttpResponse(resp);
            context.response = response;

            //Append the context to the body for easy access
            APIHelper.appendContext(response.body,context);
            deffered.resolve(response);

        },function(resp){
            var response = convertHttpResponse(resp);
            context.response = response;
            //Create error
            var error = {message:response.body,code:response.statusCode};

            //Append the context to the error object
            APIHelper.appendContext(error,context);
            deffered.reject(error);
        });

        return deffered.promise;
    }
    return executeRequest;
});

Here's the test code (this works perfectly when used for APIHelper or Config factory):

describe('Basic Injection Test', function() {

  var scope = {};
  var ctrl;

  beforeEach(module('Test'));

  it('should check if injection is being made correctly',function(){


      var $injector = angular.injector(['Test']);
      ctrl = $injector.get('XFactory');

    expect(ctrl).to.be.ok;
  });

});

Here's the files I'm including in karma.conf file:

  // list of files / patterns to load in the browser
    files: [
        '../angular.js',
        '../../node_modules/angular-mocks/angular-mocks.js',
        '../app.js',
        '../factory/APIHelper.js',
        '../factory/Config.js',
        '../factory/XFactory.js',
        'test.js'
    ],

NOTE: app.js has the following contents:

var app = angular.module('Test',[]);

app.js is just being used to help Karma find the Test module (before it was throwing an error that Test module cannot be found)

I'm using Karma for running the tests. The necessary files have been included in the "files" target of karma.conf.js file. However, when I run the tests, I get this error:

[$injector:unpr] Unknown provider: $qProvider <- $q <- XFactory

Even if I somehow remove the $q and $http services, I still get this error in this modified form:

[$injector:unpr] Unknown provider: APIHelperProvider <- APIHelper <- XFactory

Can anyone tell me how to fix this error and also explain why this is happening? I'm new to Angular Unit Testing. Therefore, I don't really know how to solve this problem. Help will be appreciated :)

2

2 Answers

0
votes

angular.injector creates a new injector instance and doesn't load core ng module by default. ng and ngMock should be loaded explicitly:

var $injector = angular.injector(['ng', 'ngMock' 'Test']);

APIHelper service isn't defined in Test module and thus isn't available.

module affects nothing in this case because it refers to another injector (the one that is used by ngMock in specs.

Consider using instead the suggested injection method in specs, inject.

0
votes

Ok so I figured out how to make it work. It was basically a Karma related problem. I simply changed the order of files that Karma was linking to. So I changed this:

  // list of files / patterns to load in the browser
    files: [
        '../angular.js',
        '../../node_modules/angular-mocks/angular-mocks.js',
        '../app.js',
        '../factory/APIHelper.js',
        '../factory/Config.js',
        '../factory/XFactory.js',
        'test.js'
    ],

To this

  // list of files / patterns to load in the browser
    files: [
        '../angular.js',
        '../../node_modules/angular-mocks/angular-mocks.js',
        '../app.js',
        '../factory/Config.js',
        '../factory/APIHelper.js',
        '../factory/XFactory.js',
        'test.js'
    ], 

I simply switched places of the Config file and the APIHelper file and that simply made the test pass.

Other than that, I think it might be helpful to mention here that any of the following syntax will work for injecting a service:

inject(function(_XFactory_){
    ctrl = _XFactory_;
});


inject(function($injector) {
   ctrl = $injector.get('XFactory');
}); 


angular.mock.inject(['XFactory', function(target) {

      expect(target).to.be.ok;

    }
]);