监视使用 $http get 用于检查功能的工厂被称为

Spying on factory which uses $http get to use to check function is callled

我编写了一个使用 $http get 方法检索 json 数据的工厂。现在我正在尝试为工厂添加一个单元测试来检查函数是否被调用

这是我的工厂

.factory('dataFactory',function($http){

function getData(){
  var request =  $http({
    method: 'GET',
    url: 'http://localhost/data.json'
  });
  return request;
  }
   var service = {
     getData : getData
   };

   return service;
});

这是我的控制器

.controller('jsonController',function($scope,$state,$stateParams,stringService,dataFactory){

  dataFactory.getData()
  .then(function(response){
    if(response){
      $scope.result = response.data.record;
      console.log(response.data.record);
    } else {
      // empty data message
    }
   })
   .catch(function(error){
    console.log('something went wrong', error);
   });
});

这是我的测试

describe('Testing factory', function() {

beforeEach(module('factories'));
var mySpy;
  mySpy = jasmine.createSpy('service');
  beforeEach(module(function ($provide){
    $provide.value('service',mySpy)
  }));
  describe('get json List', function () {
   it('should return a list', inject(function () {
    spyOn(service, 'getData');
    expect(service.getData).toHaveBeenCalled();
   }));
 });
});

它返回错误:

service is not defined

factory 定义为 object 可帮助您将控制器中的 return 方法定义为 object function,例如:

app.factory('dataFactory',function($http){
  var factory = {};

  factory.getData = function(){
    var request =  $http({
    method: 'GET',
    url: 'http://localhost/data.json'
  });

  return factory;
});

控制器

app.controller("ctrl", function(dataFactory) {
     dataFactory.getData(); //worked
})

回答

因为您正在测试 API / GET return,所以您不需要间谍!看起来你的单元测试在技术上就是我所说的 "API" 或 "Integration" 测试——你正在检查来自端点的数据 return。 (这没有什么问题,但这使测试设置有所不同)。

AngularJS 在其 ngMocks 中有一个内置服务,称为 $httpBacked.

代码(规范文件)

describe('Testing Darshuu', function() {

    beforeEach(module('Darshuu'));

    // var mySpy;
    var service = null;
    var $httpBackend;

    // Setup Spies in beforeEach() blocks!
    // mySpy = jasmine.createSpy('service');

    beforeEach(module(function($provide){
      // $provide.value('service',mySpy)
      // $provide => manually provide some object or
        // function IN PLACE OF our factory
      // Since we're in a Unit Test for the factory,
      // we actually want to inject it and NOT mock it 
      // completely.
      // See next beforeEach()
    }));

    // _..._ notation for injecting in specs
    beforeEach(inject(function(_dataFactory_, _$httpBackend_) {
      service = _dataFactory_;
      $httpBackend = _$httpBackend_;
    }));

    /*
      No call is ever made to getData() so this spec
      *should* fail, technically.
    */
    //   describe('get json List', function () {
    //   it('should return a list', inject(function () {
    //     /*
    //       No call is ever made to getData() so this spec
    //       *should* fail, technically.
    //     */
    //     spyOn(service, 'getData');
    //     expect(service.getData).toHaveBeenCalled();
    //   }));
    // });

    describe("DataFactory", function() {

      beforeEach(function() {
        // Since you know to expect an $http request, use the testing 
        // mock for it: $httpBackend
        // THEN, mock the response for the "API".
        // =====
        $httpBackend.whenGET('http://localhost/data.json').respond(200, { 
          "test": true,
          "data": [{id:1, name: "Picard"}, {id: 2, name: "Riker"}, {id: 3, name: "Data"}]
        });
      })

      it('HAS a getData() method', function() {
        expect( service.getData ).toBeDefined();
        expect( typeof service.getData ).toEqual("function");
      })

      // BECAUSE there's no AJAX mocking here OR data, it'll fail.
      // I have no idea what your hosting/API is like, but this is
      // a start I hope!
      it("getData() - returns a JSON list (array)", function() {
        service.getData().then(function(response) {
          expect( response.data ).toBeDefined();
          expect( typeof response.data ).toEqual("object");
        });
        $httpBackend.flush();
      })
    })

  });

Plnkr

Karma+Jasmine Angular Plnkr