web-dev-qa-db-ja.com

$ httpBackendを使用したAngularJSコントローラーのユニットテスト

私の人生の間、$ httpバックエンドを$ httpgetリクエストを実行するコントローラーで動作させることはできません。私は今何時間も試しました=)

これを以下の最も単純な形式に縮小しました。テストが合格した場合

  • コントローラの$ 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");
  });

});

そして、これは私がシェルで得るエラーです:

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)
16
Sir Robert

テストコードにはいくつかの問題があります。

  1. コントローラが作成されますbeforehttpMockpigで応答するように構成されます。 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");
  });
});
33
Matt York