2

我正在尝试在 Mocha 测试中使用 sinon 对 angular 的 $http 进行简单的模拟。

但是无论我尝试什么,我的间谍都没有任何结果。

searchResource.typeAhead 是我正在测试的功能。它根据其参数调用 $http ,我想确保请求是正确的。

searchResource.typeAhead 返回一个承诺,但我尝试将检查代码放入 .then() 并且它永远不会执行。

suite('Search Resource', function() {

  var injector = angular.injector(['cannonball-client-search', 'cannonball-client-core']);
  var searchResource = injector.get('SearchResource');

  suite('#typeAhead()', function () {
    setup(function () {
      this.server = sinon.fakeServer.create();
      this.server.respondWith('GET',
        config.endpoints.search.typeAhead,
        [200, {'Content-Type': 'application/json'}, '[{ "id": 12, "comment": "Hey there" }]']);
      this.spyhttp = sinon.spy(injector.get('$http'));
    });
    teardown(function () {
      this.server.restore();
    });
    test('positive', function (done) {
      searchResource.typeAhead(
        'expl',
        [{entityType: 'itementity'}],
        [{createdBy: 'Eric'}, {createdBy: 'Tal'}],
        10
      );
      this.server.respond();
      expect(this.spyhttp.calledWith({
        method: 'get',
        url: config.endpoints.search.typeAhead +
        '?query=expl&filter=entityType:itementity&orfilter=createdBy:Eric&orfilter=createdBy:Tal&limit=10'
      })).to.be.true();
      done();
    });
  });
});
4

2 回答 2

4

问题不在于诗乃的嘲弄。

如果angular.injector直接使用而不是建议angular.mock.moduleangular.mock.inject助手使用,则需要他自己使用它以及他对 Angular 注入器的了解。

明显的缺点是注入器不会在每个规范之后自动拆除(虽然它会在angular.mock.module使用时),所以所有嵌套规范都在同一个 Angular 注入器实例上运行。

在此刻

  var searchResource = injector.get('SearchResource');

SearchResource服务实例已经被注入 unmocked $http,这就是故事的结尾。即使它不会,Angular 也不可能知道this.spyhttp应该使用间谍而不是原始$http服务。它的方法可以在实例化之后被窥探

sinon.spy($http, 'get');

但不能$http发挥作用。

测试的策略angular.injector可能是

var $httpSpy;
var injector = angular.injector([
  'cannonball-client-search',
  'cannonball-client-core',
  function ($provide) {
    $provide.decorator('$http', function ($delegate) {
      return ($httpSpy = sinon.spy($delegate));
    });
  }
]);

// injector.get('$http') === $httpSpy;

请注意,这将使 Sinon 监视$http函数,而不是其方法

如果问题是关于如何使用 Sinon 处理 Angular 模拟,那么就这么简单。否则,这可能表明存在 XY 问题,而另一个答案直接解决了它($httpBackend并且$http包含它的方式正是为了使模拟 XMLHttpRequest 请求的负担不存在)。

于 2016-03-20T13:30:26.163 回答
3

Angular 在构建时考虑到了测试。前面的评论并不是说你不能使用 sinon 来模拟 $http,它只是不常见的做法,而且它肯定不会像使用 $httpBackend 那样容易。

我个人只会使用 sinon 来模拟任何不属于 Angular 的依赖项。使用 $httpBackend 提供模拟响应很容易:

$httpBackend.when('GET', '/url').respond({
    mock: 'response'
});

现在对“/url”的任何请求都使用模拟响应对象。我确定 $httpBackend 还内置了一些其他复杂的魔法来处理拦截器之类的其他事情?

于 2016-03-20T03:26:07.903 回答