Question

I'm trying to use QUnit to test an Angular controller. However, the controller has an Angular service injected into it and that service depends on the $http service. Please see this plunker. I'm trying to inject the real service into the controller and supply the mock $httpBackend, but it doesn't seem to be working as I would expect. What am I doing wrong?

The controller method:

// This is the method I want to test, but it depends 
// on a method in the service I want to mock...or maybe
// I need to inject the real service and mock $http?
$scope.sayHi = function() {
   FooService.getWord().then(function(word){
      $scope.foo = word;
   });
};

The service:

app.service('FooService', ['$http', function($http){
     return {
        getWord: function(){
           return $http.get('Word');
        }
     };
}]);

The test:

  var injector = angular.injector(['ng', 'app']);
  var http = injector.get('$httpBackend');
  var fService = injector.get('FooService');

  var init = {
    setup: function() {
      this.$scope = injector.get('$rootScope').$new();
      var $controller = injector.get('$controller');
      //var $service = injector.get('$service');

      // I don't know if I'm doing this correctly...
      $controller('FooController', {
          $scope: this.$scope,
          // Trying to inject the real service here...
          FooService: fService
          // Trying to fake the service here...
          //FooService: {
          //  getWord: function() {
          //    // how to return a fake promise?  using $httpBackend??
          //    return {
          //      'then': function() {
          //        return 'hi';
          //      }
          //    };
          //  }
          //}
      });
    }
  };

  module('Basic Controller Test', init);

  test('service injected correctly', function(){
    ok(angular.isFunction(fService.getWord));
  });

  test('sayHi from service', function() {
    http.expectGET('Word').respond('hi');

    // this is the method I'd like to test on the controller
    this.$scope.sayHi();

    // after the async service call completes, it should set scope.foo === 'hi'
    equal(this.$scope.foo, 'hi');
  });

Thanks,

Andy

Was it helpful?

Solution

I made a plunker that will improve your test:

http://plnkr.co/edit/tQBrHTMCU3IBEfUGGkWa?p=preview

You need to call http.flush() after an http call.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top