简体   繁体   English

在Jasmine单元测试中未调用Angular $ http.get成功处理程序

[英]Angular $http.get success handler not called in Jasmine unit test

I have a very basic factory service that I would like to unit test. 我有一个非常基本的工厂服务,我想对其进行单元测试。 I have tried $rootScope.$digest() and $rootScope.$apply() before the expect statements and neither the success or failure handlers are being called at all in the unit test - they are called fine in the app in the context of the controller that's using this factory, though. 我曾尝试$rootScope.$digest()$rootScope.$apply()在之前expect的语句既不是成功还是失败处理程序在单元测试中被称为在所有-他们被称为在的背景下,应用精细不过,使用该工厂的控制器。

example.service.js: example.service.js:

(function (angular) {
  'use strict';

  angular
    .module('exampleModule')
    .factory('ExampleApi', ExampleApi);

  ExampleApi.$inject = ['$http'];
  function ExampleApi($http) {
    return {
      get: getExampleData
    }

    function getExampleData() {
      return $http.get('example-endpoint');
    }
  }

})(angular);

example.service.spec.js example.service.spec.js

'use strict';

describe('Example API service', function() {
  var $httpBackend;
  var $rootScope;
  var ExampleApi;

  beforeEach(module('exampleModule'));

  beforeEach(inject(
    function(_$httpBackend_, _$rootScope_, _ExampleApi_) {
      $httpBackend = _$httpBackend_;
      $rootScope = _$rootScope_;
      ExampleApi = _ExampleApi_;
  }));

  it('calls the success handler on success', function() {
    $httpBackend
      .expectGET('example-endpoint')
      .respond(200);

    var handlerStubs = {
      success: function() {
        console.log("success called");
      },
      failure: function() {
        console.log("failure called");
      }
    }

    spyOn(handlerStubs, 'success').and.callThrough();
    spyOn(handlerStubs, 'failure').and.callThrough();
    ExampleApi.get().then(handlerStubs.success, handlerStubs.failure);
    //$rootScope.$digest();
    $rootScope.$apply();
    expect(handlerStubs.failure.calls.count()).toEqual(0);
    expect(handlerStubs.success.calls.count()).toEqual(1);
  });
});

$httpBackend mock contains a flush() method, which when called, will resolve the get request giving you synchronous control of the code under test. $httpBackend模拟包含一个flush()方法,该方法在被调用时将解析get请求,从而使您可以同步控制被测代码。 When $httpBackend.flush(); $httpBackend.flush(); is called, the expectation .expectGET is verified. 被调用时,期望.expectGET被验证。

From the Angular Docs: 从Angular Docs:

The $httpBackend used in production always responds to requests asynchronously. 生产中使用的$ httpBackend始终异步响应请求。 If we preserved this behavior in unit testing, we'd have to create async unit tests, which are hard to write, to follow and to maintain. 如果我们在单元测试中保留了这种行为,那么我们将不得不创建一个异步单元测试,它很难编写,遵循和维护。 But neither can the testing mock respond synchronously; 但是测试模拟不能同步响应。 that would change the execution of the code under test. 这将改变被测代码的执行。 For this reason, the mock $httpBackend has a flush() method, which allows the test to explicitly flush pending requests. 因此,模拟$ httpBackend具有flush()方法,该方法允许测试显式刷新挂起的请求。 This preserves the async api of the backend, while allowing the test to execute synchronously. 这将保留后端的异步api,同时允许测试同步执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM