angularjs - 使用 Jasmine 测试 Angular Controller 对带有 Promise 返回的服务的调用的最佳方法

标签 angularjs testing mocking jasmine promise

在寻找好的答案/样本一周后,我决定发布我的问题。

我需要知道如何编写和测试这样的代码的最佳方式:

Controller

// my.controller.js
(function () {

  'use strict';

  angular.module('myApp.myModule').controller('Awesome', Awesome);

  function Awesome($http, $state, AwesomeService) {

    var vm = this; // using 'controllerAs' style

    vm.init = init;
    vm.awesomeThingToDo = awesomeThingToDo;

    vm.init();

    function awesomeThingToDo() {
      AwesomeService.awesomeThingToDo().then(function (data) {
        vm.awesomeMessage = data.awesomeMessage;
      });
    }

    function init() {
        vm.awesomeThingToDo(); // Should be ready on page start
    }
  }
})();

服务

// my.service.js
(function () {
  'use strict';

  angular.module('myApp.myModule').factory('AwesomeService', AwesomeService);

  function AwesomeService($resource, $http) {

    var service = {
      awesomeThingToDo: awesomeThingToDo
    }

    return service;

    function awesomeThingToDo() {

      var promise = $http.get("/my-backend/api/awesome").then(function (response) {
          return response.data;
        });

      return promise;
    }
  }
})();

我的应用在这种结构下运行良好。我的服务单元测试也很好。 但是我不知道如何在 Controller 上进行单元测试。

我试过这样的:

规范

// my.controller.spec.js
(function () {
  'use strict';

  describe("Awesome Controller Tests", function() {

    beforeEach(module('myApp.myModule'));

    var vm, awesomeServiceMock;

    beforeEach(function () {
      awesomeServiceMock = { Is this a good (or the best) way to mock the service?
        awesomeThingToDo: function() {
          return {
            then: function() {}
          }
        }
      };
    });

    beforeEach(inject(function ($controller) {
      vm = $controller('Awesome', {AwesomeService : awesomeServiceMock});
    }));

    it("Should return an awesome message", function () {
      // I don't know another way do to it... :(
      spyOn(awesomeServiceMock, "awesomeThingToDo").and.callFake(function() {
        return {
          then: function() {
            vm.awesomeMessage = 'It is awesome!'; // <-- I think I shouldn't do this.
          }
        }
      });

      vm.awesomeThingToDo(); // Call to real controller method which should call the mock service method.

      expect(vm.awesomeMessage).toEqual('It is awesome!'); // It works. But ONLY because I wrote the vm.awesomeMessage above.

    });

  });
})();

我的应用使用 Angular 1.2.28 和 Jasmine 2.1.3(带有 Grunt 和 Karma)。

更新:已解决!

it("Should return an awesome message", function () {
  // Solved with callback parameter
  spyOn(awesomeServiceMock, "awesomeThingToDo").and.callFake(function(callback) {
    return {
      then: function(callback) {
        callback({awesomeMessage: 'It is awesome!'}); //callback call works fine! :D
      }
    }
  });

最佳答案

我用一个可能的(坏的)解决方案更新了问题:

it("Should return an awesome message", function () {
  // Solved with callback parameter
  spyOn(awesomeServiceMock, "awesomeThingToDo").and.callFake(function(callback) {
    return {
      then: function(callback) {
        callback({awesomeMessage: 'It is awesome!'}); //callback call works fine! :D
      }
    }
  });

我使用回调来传递模拟参数并调用真正的实现。 :D

关于angularjs - 使用 Jasmine 测试 Angular Controller 对带有 Promise 返回的服务的调用的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36266732/

相关文章:

javascript - Angular 不返回我的自定义 JSON 文件

javascript - AngularJS:ng-repeat并不总是显示数据

c++ - Proveit.com C++ 测试

go - TestMain - 没有要运行的测试

c# - 测试依赖于 subview 模型的 View 模型的最佳方法是什么?

unit-testing - Grails测试中的模拟配置

python - mock __main__

javascript - Object.keys() 在 ng-options 中不起作用

javascript - 加载js文件时出现404错误

unit-testing - 如何使用 Microsoft Fakes 框架填充实例方法?