AngularJS 使用 HttpBackend.whenGet 的单元测试未达到 return 预期结果

AngularJS Unit Test using HttpBackend.whenGet doesn't return expected result

根据 ngMock 的 Angular 文档,$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);
    });

});

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

Error: Unexpected request: GET App/Main/login.html

这意味着 ui.routing 服务以某种方式被调用。所以我通过在 beforeEach.

中添加 $httpBackend.expectGET... 来处理这个问题

为什么我还要使用 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
    }
}]);

您的 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);

});

My question is why do I have to even use the flush method?

因为编写异步单元测试可能是地狱。所以我们需要使用 flush 方法使我们的异步测试同步,这让生活变得更轻松,因为我们不再需要创建大量虚假承诺并弄清楚 done() 回调告诉我们的测试框架测试结束等等等等

Why does it trigger ui.routing when that has nothing to do with my unit test?

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

这可能会很痛苦,但我发现使用像 bardJS 这样的辅助库可能是解决 ui-router 问题的最快方法,而且它还删除了很多样板文件您需要为 Angular 单元测试编写代码。