单元测试angular $ httpBackend service

时间:2016-06-30 18:23:52

标签: angularjs unit-testing jasmine karma-jasmine

我现在有一个项目,我们需要暂时嘲笑后端服务器,并且我们在应用程序$httpBackend功能上使用.run。我需要对包含$httpBackend的服务进行单元测试,因为我们将对我们将要覆盖的服务器进行大量模拟调用。所以现在这就是我所拥有的。作为我的问题的前言,当我从简单页面上的控制器调用mockDataService.getWorkflowTask时,当前设置有效。

我的服务器更换服务:

angular.module('app').run(function ($httpBackend, $resource, FakeBackendService) {
    // TODO: add all necessary http intercepts.  
    $httpBackend.whenGET('JSON file').respond(function (method, url, data) {
        var request = new XMLHttpRequest();
        request.open('GET', url, false);
        request.send(null);
        return [request.status, request.response, {}];
    });
    $httpBackend.whenGET(/.*/).respond(function (method, url, data) {

        return [200, FakeBackendService.getWorkflowTasks(), {}];
    });
});

以下是FakeBackendService的服务:

(function () {
    'use strict';

    var injectParams = [];

    function service(lodash) {
        var vm = this;

        var ret = {
            getWorkflowTasks: getWorkflowTasks
        };

        function getWorkflowTasks() {
            if (vm.workflowtasks.length < 1) {
                vm.workflowtasks = loadWorkflowTasks("Some JSON file");
            }
            return vm.workflowtasks;
        };

        function loadWorkflowTasks(file) {
            var workflowTasks = [];
            var request = new XMLHttpRequest();
            request.open("GET", file, false);
            request.send(null);

            if (request.status == 200) {
                workflowTasks = angular.fromJson(request.response);
            }
            return workflowTasks;
        };

        function init() {
            vm.workflowtasks = [];
        }

        init();

        return ret;
    }

    service.$inject = injectParams;
    angular.module('mock.FakeBackendService', []).service('FakeBackendService', service);
})();

所以这是目前的后端服务器替换模拟。以下是我的数据处理服务,其中包含对$http.get(blah blah blah)的调用。

(function () {
    'use strict';

    var injectParams = ['$http', '$q', 'mockConfigService', '$httpBackend'];

    function factory($http, $q, configService, $httpBackend) {
        var vm = this;

        var factory = {
            getWorkflowTask: getWorkflowTask
        };

        function getWorkflowTask(str) {
            return getResource(str);
        }

        function init() {
            // Get the URL we will be using to get data from
            vm.dataServiceURL = configService.getDataServiceURL();
        }

        function getResource(baseResource) {
            var resource = vm.dataServiceURL + baseResource;

            return $http.get(resource).then(function (response) {
                if (typeof response.data == 'object') {
                    // Got valid response
                    return $q.resolve(response.data);
                }
                else {
                    // Invalid response
                    return $q.reject(response.data);
                }
            }, function (response) {
                // Something went wrong
                return $q.reject(response.data);
            });
        }
        init();

        return factory;
    };

    factory.$inject = injectParams;

    angular.module('mock.dataService', []).factory('mockDataService', factory);
}());

现在进行Jasmine-Karma单元测试。

describe("HTTP Backend Mock testing", function () {

    beforeEach(angular.mock.module("app"));
    beforeEach(angular.mock.module("mock.FakeBackendService"));
    beforeEach(angular.mock.module("mock.configService"));
    beforeEach(angular.mock.module("mock.dataService"));

    it("Get the workflow task", angular.mock.inject(function (mockDataService) {
        var valid = "";

        var promise = mockDataService.getWorkflowTask('http://localhost/foo');

        promise.then(function (response) {
            valid = "Success";
        }, function (response) {
            valid = "Failure";
        });

        expect(valid).toBe("Success");
    }));
});

现在回答这个问题。所以,我首先要说的是我是AngularJS世界的新手,对Jasmine来说更是如此。无论如何,当我调试单元测试时,我发现承诺的状态仍然是0,我总是得到预期&#39;&#39;成功&#39;成功&#39;告诉我我永远不会解决(希望我使用正确的术语)来自$http mockDataService服务的承诺。我试过玩一些,试着看看有没有人以前做过这种事情。我发现了大量的例子,其中$httpBackend在测试中被嘲笑但没有像我尝试的那样。任何想法或建议都会很棒。感谢。

EDIT获得了一个稍微有效的解决方案

所以我决定通过run()服务,并在expectGET().respond()中做同样的回复。

describe("HTTP Backend Mock testing", function () {
    beforeEach(angular.mock.module("app"));
    beforeEach(angular.mock.module("mock.FakeBackendService"));
    beforeEach(angular.mock.module("mock.configService"));
    beforeEach(angular.mock.module("mock.dataService"));

    it("Get the workflow task", angular.mock.inject(function (mockDataService, $httpBackend, FakeBackendService) {
        var valid = "";
        $httpBackend.expectGET('http://server:80/api/foo').respond(200, FakeBackendService.getWorkflowTasks());
        var promise = mockDataService.getWorkflowTask('foo');


        promise.then(function (response) {
            valid = "Success";
        }, function (response) {
            valid = "Failure";
        });
        $httpBackend.flush();

        expect(valid).toBe("Success");
    }));
});

这种方式解决了run()的测试问题,因为目标是验证 1)正则表达式匹配调用正确的FakeBackendService 2) FakeBackendService返回正确的文件并实际加载它。我想我可以通过模仿expectGET中的相同正则表达式来做到这一点。但是,我会稍微公开一下,看看是否有人知道如何让run()起作用。

2 个答案:

答案 0 :(得分:1)

除非您在测试结束前强制执行此承诺,否则承诺无法解决。这是一种这样的方法:

    $httpBackend.expectGET(......).respond(200, 'abc');

    var promise = mockDataService.getWorkflowTask('http://localhost/foo');

    promise.then(function (response) {
        valid = "Success";
    }, function (response) {
        valid = "Failure";
    });

    //new code here
    $httpBackend.flush();

    expect(valid).toBe("Success");

这将强制承诺解决,您的测试应该通过。您还需要将$ httpBackend服务注入测试。

答案 1 :(得分:0)

angular.module('mock.dataService', [])
  .service('mockDataService', function($http) {
    this.getWorkflowTask = function(url) {
      return $http.get(url)
    }
  })

describe('HTTP Backend Mock testing', function() {
  var $httpBackend
  beforeEach(angular.mock.module("mock.dataService"));
  beforeEach(inject(function(_$httpBackend_) {
    $httpBackend = _$httpBackend_
  }))

  it("Get the workflow task", angular.mock.inject(function(mockDataService) {
    $httpBackend.expectGET('http://localhost/foo').respond(200);

    var promise = mockDataService.getWorkflowTask('http://localhost/foo');

    promise.then(function(response) {
      valid = "Success";
    }, function(response) {
      valid = "Failure";
    });

    $httpBackend.flush();

    expect(valid).toBe("Success");
  }));
})
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>

相关问题