测试 Angular 控制器并监视模拟服务

Testing Angular controller and spying on a mocked service

所以我正在学习如何在 Angular 中进行测试,并遵循了一个教程,该教程展示了如何模拟您的控制器使用的服务。似乎无法弄清楚为什么它不起作用所以我转向这里寻求帮助。任何关于我做错了什么以及如何让它工作的建议都将不胜感激。

错误:需要一个间谍,但得到了函数。

// Controller

'use strict';

angular.module('tikrApp')
  .controller('MessageCtrl', ['$scope', '$state', 'messageService', function ($scope, $state, messageService) {

    /**
     * Set $state on the scope to access it in the views
     */
    $scope.$state = $state;

   /**
    * Fetches a messages list that belongs to the authenticated user
    */
   $scope.inbox = function () {
     messageService.inbox().then(function (messages) {
       $scope.messages = messages;
     });
   };

  /**
   * Fetches a message
   */
  $scope.show = function (message) {
    messageService.update(message, { read: true }).then(function (result) {
      if (result) {
        $scope.message = message;
        $scope.message.read = true;
      }
    });
  };

  /**
   * Prioritizes the message for the user
   */
  $scope.starred = function (message) {
    messageService.update(message, { starred: true }).then(function (result) {
      if (result) message.starred = true;
    });
  };

  /**
   * Creates a new private message to a user
   */
  $scope.create = function (newMessage) {
    messageService.create(newMessage).then(function () {
      $scope.messages.push(newMessage);
      $state.transitionTo('inbox.messages');
    }, function () {
      $state.transitionTo('inbox.messages.create');
    });
  };

  $scope.inbox();
  // $state.transitionTo('inbox.messages');

}]);

// Spec

'use strict';

describe('Controller: MessageCtrl', function () {

  var scope;
  var messageService;

  beforeEach(function () {

    var mockMessageService = {};
    module('tikrApp', function ($provide) {
      $provide.value('messageService', mockMessageService);
    });

    inject(function ($q) {
      mockMessageService.messages = [
        { to: '123', from: '123', title: 'Title 1', content: 'Content 1', read: false },
        { to: '123', from: '123', title: 'Title 2', content: 'Content 2', read: false },
        { to: '123', from: '123', title: 'Title 3', content: 'Content 3', read: false }
      ];

      mockMessageService.inbox = function () {
        var defer = $q.defer();
        defer.resolve(this.messages);
        return defer.promise;
      };

      mockMessageService.create = function (newMessage) {
        var defer = $q.defer();
        defer.resolve();
        return defer.promise;
      };

    });

  });

  beforeEach(inject(function ($controller, $rootScope, _messageService_) {

    scope = $rootScope.$new();
    messageService = _messageService_;
    $controller('MessageCtrl', {
      $scope: scope,
      messageService: messageService
    });

    scope.$digest();

  }));

  it('should list all messages in the users inbox', function () {
    // tried this way
    spyOn(scope, 'inbox');
    // and this way
    spyOn(messageService, 'inbox');
    expect(messageService.inbox).toHaveBeenCalled();
  });

});

这就是我通常对控制器-服务通信进行单元测试的方式。我发现这种方法更简单:

'use strict';
describe('countryController', function () {
    var scope;
    var searchService;

    beforeEach(module('app'));
    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        mockSearchService();
        createController($controller);
    }));

    it('loads flights after view is shown', function () {
        scope.loadFlights();
        expect(searchService.loadFlights).toHaveBeenCalled();
    });

    function mockSearchService() {
        searchService = jasmine.createSpyObj('searchService', ['loadFlights']);
    }

    function createController($controller) {
        $controller('countryController', {
            $scope: scope,
            searchService: searchService
        });
    }
});