【问题标题】:Unit testing AngularJS controller with $httpBackend使用 $httpBackend 对 AngularJS 控制器进行单元测试
【发布时间】:2013-05-01 22:24:05
【问题描述】:

在我的一生中,我无法让 $httpBackend 在执行 $http get 请求的控制器上工作。我已经尝试了几个小时了 =)

我已将其简化为以下最简单的形式。如果我测试通过了

  • 注释掉控制器中的$http.get()请求
  • 注释掉测试中的“httpMock.flush()”
  • 并更改“猪”和“狗”以匹配

也就是说,它是一个有效的工作测试和应用程序。

如果我把它放回去,我会得到底部显示的错误。


app/js/app.js

// Declare a module which depends on filters and services.
var myApp = angular
  .module('myApp', ['ngRoute', 'myApp.filters', 'myApp.services',
                              'myApp.directives'])
  .config(['$routeProvider' , function($routeProvider) {

    $routeProvider
      .when("/dashboard", {
        templateUrl: "partials/dashboard.html",
        controller: cDashboard
      })

      .otherwise({redirectTo: "/dashboard"});
  }]);

// Pre-define our main namespace modules.
angular.module('myApp.directives' , []);
angular.module('myApp.filters'    , []);
angular.module('myApp.services'   , []);
angular.module('myApp.controllers', []);

app/js/controller.js

function cDashboard ($scope, $http) {
  $scope.data = "dog";

  // Fetch the actual data.
  $http.get("/data")
    .success(function (data) { $scope.data = data })
    .error(function () {});
}

cDashboard.$inject = [ '$scope', '$http' ];

test/unit/controllerSpec.js

describe('cDashboard', function(){
  var scope, ctrl, httpMock;

  beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend) {
    scope = $rootScope.$new();
    ctrl = $controller('cDashboard', {$scope: scope});

    httpMock = $httpBackend;
    httpMock.when("GET", "/data").respond("pig");
  }));

  it("should get 'pig' from '/data'", function () {
    httpMock.expectGET("/data").respond("pig");
    expect(scope.data).toBe("pig");
  });

});

这是我在 shell 中遇到的错误:

INFO [watcher]: Changed file "/home/myApp/test/unit/controller/cDashboard.js".
Chrome 26.0 (Linux) cDashboard should get 'pig' from '/data' FAILED
    Error: No pending request to flush !
        at Error (<anonymous>)
        at Function.$httpBackend.flush (/home/myApp/test/lib/angular/angular-mocks.js:1171:34)
        at null.<anonymous> (/home/myApp/test/unit/controller/cDashboard.js:15:18)
Chrome 26.0 (Linux): Executed 1 of 1 (1 FAILED) (0.326 secs / 0.008 secs)

【问题讨论】:

    标签: unit-testing angularjs controller


    【解决方案1】:

    您的测试代码中有几个问题:

    1. 控制器创建之前 httpMock 被配置为以pig 响应。 expectGet 调用应该在实例化控制器之前发生。
    2. httpMock 需要刷新请求
    3. httMock.when 是不必要的,只要您有 expectGet

    工作示例:http://plnkr.co/edit/lUkDMrsy1KJNai3ndtng?p=preview

    describe('cDashboard', function(){
      var scope, controllerService, httpMock;
    
      beforeEach(inject(function ($rootScope, $controller, $httpBackend) {
        scope = $rootScope.$new();
        controllerService = $controller;
        httpMock = $httpBackend;
      }));
    
      it("should get 'pig' from '/data'", function () {
        httpMock.expectGET("/data").respond("pig");
        ctrl = controllerService('cDashboard', {$scope: scope});
        httpMock.flush();
        expect(scope.data).toBe("pig");
      });
    });
    

    【讨论】:

    • 谢谢!在实例化控制器之前必须发生 .expectGET 的麻烦和解释非常有帮助。
    猜你喜欢
    • 2013-12-23
    • 2016-02-12
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多