对使用$ http的控制器进行单元测试

时间:2013-03-20 16:57:19

标签: unit-testing angularjs mocking jasmine

我有一个简单的控制器,我需要它做的第一件事是为范围分配一个值。

function TestCtrl($scope, $http) {
    $scope.listForms = 'some list';
}

控制器的以下测试按预期工作:

describe('Testing a controller', function() {

    var ctrl, scope, httpMock;

    beforeEach(inject(function($injector) {
        scope = $injector.get('$rootScope').$new();
        ctrl = $injector.get('$controller');
        ctrl(TestCtrl, { $scope: scope });
    }));

    it("assigns to scope", function() {
      expect(scope.listForms).toMatch("some list");
    });
});

但是当我更改函数以从我的API获取列表时

function TestCtrl($scope, $http) {
  $http.get('/api/listForms').success(function(list) {
    $scope.aListOfForms = 'some list';
  });
}

并且测试更改为

describe('Testing a controller', function() {

    var ctrl, scope, httpMock;

    beforeEach(inject(function($injector) {
        httpMock = $injector.get('$httpBackend');

        scope = $injector.get('$rootScope').$new();
        httpMock.when('GET', '/tactical/api/listOrderForms').respond("an order form");

        ctrl = $injector.get('$controller');
        ctrl(TestCtrl, {
            $scope: scope,
            $http: httpMock
        });
    }));

    it("gets the list from the api and assigns it to scope", function() {
      httpMock.expectGET('tactical/api/listOrderForms');
      expect(scope.orderFormList).toMatch("an order form");
      httpMock.flush();
    });
});

我收到以下错误:

TypeError: 'undefined' is not a function
Expected undefined to match 'an order form'.
Error: No pending request to flush !

有谁知道我做错了什么?提前谢谢。

3 个答案:

答案 0 :(得分:8)

$ http使用$httpBackend与外部资源进行通信。您已经模拟了$httpBackend,但控制器仍然需要通过$http接口与之通信。

这应该这样做:

describe('Testing a controller', function() {

    var ctrl, scope, httpMock;

    beforeEach(inject(function($controller, $rootScope, $httpBackend) {
        httpMock = $httpBackend;

        scope = $rootScope.$new();
        httpMock.when('GET', '/tactical/api/listOrderForms').respond("an order form");

        ctrl = $controller;
        ctrl(TestCtrl, {
            $scope: scope
        });
    }));

    it("gets the list from the api and assigns it to scope", function() {
      httpMock.expectGET('tactical/api/listOrderForms');
      httpMock.flush();
      expect(scope.orderFormList).toMatch("an order form");
    });
});

答案 1 :(得分:3)

您无法手动将$ http服务替换为控制器的$ httpBackend服务。

更改

    ctrl(TestCtrl, {
        $scope: scope,
        $http: httpMock
    });

    ctrl(TestCtrl, {
        $scope: scope
    });

它应该有用。

答案 2 :(得分:0)

您需要在expect()之前调用httpMock.flush()。 flush调用模拟从“后端”返回的响应,调用绑定到http请求的success函数。