使用HttpBackend.whenGet的AngularJS单元测试不会返回预期结果

时间:2015-07-29 22:00:56

标签: angularjs unit-testing jasmine

根据针对ngMock的Angular文档,$ httpBackend方法应该拦截$ http服务请求并提供指定的响应。我假设模拟$ httpBackend方法将是同步的,以使测试更容易。但是result.test最终没有被定义。

describe('Http requests', function () {
    var scope, $httpBackend, constituents;

    beforeEach(module('main'));

    beforeEach(inject(function (_$httpBackend_, _constituents_) {
        constituents = _constituents_;
        $httpBackend = _$httpBackend_;
        $httpBackend.expectGET("App/Main/login.html").respond(200);
    }));

    it('Should get the constituents', function () {
        $httpBackend.whenGET(webServicesPath + "api/constituents/all-constituents").respond(200, { "test": true });
        var result = constituents.getAllConstituents();
        $httpBackend.flush();
        expect(result.$$state.value.test).toEqual(true);
    });

});

我尝试使用$ httpBackend.flush(),但这会产生意想不到的后果......

  

错误:意外请求:GET App / Main / login.html

这意味着以某种方式调用了ui.routing服务。所以我通过在$httpBackend.expectGET...中添加beforeEach来处理这个问题。

为什么我甚至不得不使用flush方法?看起来过于复杂。当它与我的单元测试无关时,为什么会触发ui.routing?

作为参考,这是工厂使用的

app.factory('constituents', ['$http', '$log', function ($http, $log) {
    function getAllConstituents() {
        return $http.get(webServicesPath + "api/constituents/all-constituents").then(
            function (response) {
                return response.data;
            },
            function (response) {
                $log.error("Load Constituents - " + response.status + " " + response.statusText);
                return;
            }
        );
    }
    return {
        getAllConstituents: getAllConstituents
    }
}]);

1 个答案:

答案 0 :(得分:5)

您的results变量是承诺,而不是$http请求的结果。您必须执行以下操作才能访问结果:

it('Should get the constituents', function () {
    var result;

    $httpBackend.whenGET('foo.json').respond(200, { "test": true });

    constituents
      .getAllConstituents()
      .then(function(response){
        result = response;
      });

    $httpBackend.flush();
    expect(result.test).toEqual(true);

});
  

我的问题是为什么我甚至不得不使用flush方法?

因为编写异步单元测试可能很糟糕。因此,我们需要使用flush方法使我们的异步测试同步,这使得生活变得更加容易,因为我们不再需要创建假承诺的负载,并找出告诉我们的测试框架的done()回调的位置测试结束等等。

  

为什么当它与我的无关时触发ui.routing   单元测试?

您可以在此SO问题中阅读更多相关信息

UI-router interfers with $httpbackend unit test, angular js

这可能很痛苦,但我发现使用像bardJS这样的帮助程序库可能是让ui-router问题消失的最快方法,它也删除了很多样板文件您需要为Angular单元测试编写。