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

nua*_*der 0 unit-testing jasmine angularjs

根据Angular docs for ngMock,$ httpBackend when方法应该拦截$ 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);
    });

});
Run Code Online (Sandbox Code Playgroud)

我尝试使用$ 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
    }
}]);
Run Code Online (Sandbox Code Playgroud)

Mat*_*itt 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);

});
Run Code Online (Sandbox Code Playgroud)

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

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

当与单元测试无关时,为什么会触发ui.routing?

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

UI路由器干扰$ httpbackend单元测试,角度js

这可能是一种痛苦,但我发现使用像bardJS这样的辅助库可能是ui-router解决问题的最快方法,它也消除了你需要为Angular单元测试编写的大量样板.