如何监视服务以测试它 - AngularJS / Jasmine

时间:2016-06-17 15:14:24

标签: javascript angularjs unit-testing jasmine code-coverage

尝试过我在互联网上找到的所有内容,但没有成功。试图在我的服务中测试一个功能,但根据我的报道,我永远不会访问它。任何帮助将不胜感激:)

服务:

'use strict';

angular.module('Service').service('configService', function(
  $rootScope, $http) {
  var configObj = null;
  return {

    getConfig: function() {
      if (configObj != null) {
        console.log("returning cached config");
        return configObj;
      }
      else {
        return $http.get('conf.json').then(function(res) {
          $http.get(res.confLocation).then(function(
            locationResponse) {
            configObj = locationResponse;
            $rootScope.configObj = configObj;
            console.log($rootScope.configObj);
            return configObj;
          });
        });
      }
    }
  };
});
在我尝试的测试中永远不会访问

getConfig

ServiceTests:

'use strict';
describe('Service: configService', function() {

  // load the controller's module
  beforeEach(module('Service'));

  var configService, $httpBackend, results, tstLocation, tstRes;
  var tstConfig = {
    "confLocation": "local-dev-conf.json"
  };

  var tstConfigEmpty = {};
  var tstConfigObjEmpty = {};

  var tstConfigObj = {
    "AWS": {
      "region": "us-east-1",
      "endpoint": "http://localhost:8133"
    }
  };

  // Initialize the controller and a mock scope
  beforeEach(inject(function(_configService_, _$httpBackend_) {
    inject(function($rootScope) {
      $rootScope.USERNAME = 'TESTER';
      $rootScope.configObj = tstConfigObj;
      $rootScope.locationResponse = tstLocation;
      $rootScope.res = tstRes;
    });

    configService = _configService_;
    $httpBackend = _$httpBackend_;

    //Problem here??
    spyOn(configService, 'getConfig').and.callFake(function() {
      return {
        then: function() {
          return "something";
        }
      };
    });

  }));
  it('should return a promise', function() {
    expect(configService.getConfig().then).toBeDefined();
  });

  it('should test backend stuff', inject(function() {

    results = configService.getConfig(tstConfig);
    $httpBackend.expectGET('conf.json').respond(tstConfig);
    $httpBackend.expectGET('local-dev-conf.json').respond(tstConfigObj);
    $httpBackend.flush();
  }));

  //Thanks Miles
  it('should check if it was called', inject(function() {
    results = configService.getConfig().then();
    expect(configService.getConfig).toHaveBeenCalled();

    });
    // console.log(results);
  }));

  it('should check for a null configObj', inject(function() {
    results = configService.getConfig(tstConfigObjEmpty).then(function() {
      expect(results).toBe(null);
    });
    // console.log(results);
    // console.log(tstConfigObj);
  }));

  it('should check for a non-null configObj', inject(function() {
    results = configService.getConfig(tstConfigObj).then(function() {

      // Any string is accepted right now -- Why??
      expect(results).toEqual("returning cached config");
      expect(results).toBe("returning cached config");
      expect(results).toBe("your mom"); // SHOULDN'T BE WORKING BUT DOES
      expect(results).toEqual("Object{AWS: Object{region: 'us-east-1', endpoint: 'http://localhost:8133'}}");
      expect(results).toBe("Object{AWS: Object{region: 'us-east-1', endpoint: 'http://localhost:8133'}}");
    });
    // console.log(results);
    // console.log(tstConfigObj);
  }));

  it('should check for null file', inject(function() {
    results = configService.getConfig(tstConfigEmpty).then(function() {
      expect(results).toEqual(null);
      expect(results).toBe(null);
    });
  }));

  it('should test a valid file', inject(function() {
    results = configService.getConfig(tstConfig).then(function() {
      expect(results).not.toBe(null);
      expect(results).toEqual("Object{confLocation: 'local-dev-conf.json'}");
    })
});

我认为我在测试中使用spyOn错误,或者没有正确访问 getConfig 。想法?

编辑:Here is my code coverage

编辑2:由于Miles发现问题,更改了测试3,但测试覆盖率仍然没有更新。正如艾米指出的那样,我的间谍逻辑出了问题。我似乎不应该使用callFake吗?

编辑3:现在感谢Miles访问该功能。必须将我的间谍改为:

spyOn(configService, 'getConfig').and.callThrough(); 

然后添加测试用例:

results = configService.getConfig(tstConfig).then();   
expect(configService.getConfig).toHaveBeenCalled();

Coverage now (still needs work)

3 个答案:

答案 0 :(得分:1)

您正在调用假冒而非功能。因此函数内部的逻辑不会被调用。

答案 1 :(得分:0)

您使用的是什么版本的Jasmine?在Jasmine 2.0中添加了and.callFake语法。也许测试套件只需要指向新版本。

Jasmine 1.3 Docs

Jasmine 2.0 Docs

答案 2 :(得分:0)

你有一个问题:

results = configService.getConfig(tstConfigObj).then(function() {
  expect(results).toHaveBeenCalled();
  expect(results).toHaveBeenCalledWith(tstConfigObj);
});

getConfig不带参数,then也不带参数。省略这些错误,results会为then分配字符串“something”。即使expect语句触发,您似乎也在测试是否已调用字符串。试试这个:

results = configService.getConfig().then();
expect(configService.getConfig).toHaveBeenCalled();