javascript - 如何测试返回 $timeout promise 且内部包含 $http.get 的 AngularJS 工厂方法?

标签 javascript angularjs unit-testing jasmine

出于特定目的,我必须编写一个返回 $timeout promise 的工厂方法,该 promise 在其内部返回一个 $http.get promise 。

我想测试对我的工厂方法的调用是否会使用正确的模拟 URL (mocked-get-path) 调用 $http.get

这是我的工厂代码:

(function() {
  'use strict';

  angular.module('MyApp', []);

  angular.module('MyApp')
    .constant("ROUTES", {
      get: "real-get-path"
    });

  angular.module('MyApp')
    .factory('MyFactory', ['$http', '$timeout', 'ROUTES', MyFactory]);

  function MyFactory($http, $timeout, ROUTES) {
    return {
      myGet: function(id) {
        var random = Math.random() * 1000;
        return $timeout(function () {
            return $http.get(ROUTES.get, {
              params: { id: id }
            })
              .then(function() {
                return response.data;
              });
        }, random);
      }
    };
  }
})();

以及我的测试规范:

describe('simple factory test', function() {
  var $http, $timeout, scope, MyFactory;

  var ROUTES = {
      get: 'mocked-get-path'
  };

  beforeEach(module('MyApp', function ($provide) {
      $provide.constant('ROUTES', ROUTES);
  }));

  beforeEach(module('MyApp'));

  beforeEach(inject(function(_$rootScope_, _$http_, _$timeout_, _MyFactory_) {
    scope = _$rootScope_.$new();
    $http = _$http_;
    $timeout = _$timeout_;
    MyFactory = _MyFactory_;
  }));

  it('should use ROUTES.get on method myGet', function(done) {
    spyOn(Math, "random").and.returnValue(0.01);

    MyFactory.myGet('elem1')
      .then(function(res) {
        expect($http.get).toHaveBeenCalledWith(ROUTES.get);
        done();
      });
    $timeout.flush();
  });
});

你可以看到我尝试在then内为$http.get编写一个expect,但是没有成功.

我从 Jasmine 收到此错误:

Error: Unexpected request: GET mocked-get-path?id=elem1

我做了一个Plunker:https://plnkr.co/edit/Ia6Q6GvKZOkNU2B8GrO1

我做错了什么?

最佳答案

测试 $http 时,您将需要使用 $httpBackend.when

就您而言:

it('should use ROUTES.get on method myGet', function(done) {
  spyOn(Math, "random").and.returnValue(0.01);
  spyOn($http, "get").and.callThrough();

  MyFactory.myGet('elem1')
    .then(function(res) {
      expect($http.get).toHaveBeenCalledWith(ROUTES.get, {params: {id: 'elem1'}});
      done();
    });

  $httpBackend
    .when('GET', "mocked-get-path?id=elem1")
    .respond(200, { foo: 'bar' });

  $timeout.flush(100);

  $timeout.verifyNoPendingTasks();
  $httpBackend.flush();

});

这将导致 $httpBackend 成功完成您的请求,从而允许您的 .then 执行预期。

Plunkr showing solution

ngmock fundamentals

我希望这有帮助!祝你有美好的一天!

关于javascript - 如何测试返回 $timeout promise 且内部包含 $http.get 的 AngularJS 工厂方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40155513/

相关文章:

javascript - 循环遍历 JSON 中的每个项目以显示平面信息

javascript - 在 Gulp 中运行所有任务后,如何删除文件夹及其内容?

javascript - 您从哪里获得与 timezone-js 一起使用的 Olson 时区数据库文件?

javascript - 在 angularjs 指令中不起作用的标签

javascript - Angular Directive(指令)无法访问范围

javascript - 如何将这些日期对象合并为一个对象

unit-testing - 当使用返回流的存储库对 View 模型进行单元测试时,将其转换为实时数据时会发生错误

javascript - PhantomJS QUnitTeamCityDriver QUnit 测试运行

node.js - clearTimeout 测试不适用于 jest.useFakeTimers()

javascript - 用于 Handlebars 助手的 JSdoc doclet