2016-07-26 4 views
0

カルマとジャスミンを使用してイオン性アプリケーションにいくつかのテストを追加しています。この瞬間、私は角度ログインコントローラのテストをしようとしています。しかし、コントローラを作成し、すべての外部依存関係をモックする注入文を実行していないように見えます。私がしようとしてすべての場所の上に検索されているカルマ/ジャスミン試験では、注入器を使用しないイオン性アプリケーション

describe("LoginController", function() { 
    var controller, 
     deferredLogin, 
     translateMock, 
     stateMock, 
     ionicPopupMock, 
     localStorageMock, 
     sessionServiceMock, 
     userServiceMock; 

    beforeEach(module("myApp")); 

    beforeEach(module(function($provide, $urlRouterProvider) { 
    $provide.value("$ionicTemplateCache", function() {}); 
    $urlRouterProvider.deferIntercept(); 
    })); 

    beforeEach(inject(function($controller, $q) { 
    deferredLogin = $q.defer(); 

    sessionServiceMock = { 
     login: jasmine.createSpy("login spy") 
        .and.returnValue(deferredLogin.promise) 
    }; 

    translateMock = jasmine.createSpyObj("$translate spy", ["instant"]); 

    stateMock = jasmine.createSpyObj("$state spy", ["go"]); 

    ionicPopupMock = jasmine.createSpyObj("$ionicPopup spy", ["alert"]); 

    localStorageMock = jasmine.createSpyObj("$localStorage spy", ["getItem"]); 

    userServiceMock = jasmine.createSpyObj("userService spy", ["isAuthenticated"]); 

    controller = $controller("LoginController", { 
     "$translate": translateMock, 
     "$state": stateMock, 
     "$ionicPopup": ionicPopupMock, 
     "$localStorage": localStorageMock, 
     "sessionService": sessionServiceMock, 
     "userService": userServiceMock 
    }); 
    })); 

    describe("#login", function() { 
    beforeEach(inject(function(_$rootScope_) { 
     $rootScope = _$rootScope_; 
     controller.email = "[email protected]"; 
     controller.password = "foobarfoo"; 
     controller.login(); 
    })); 

    it("should call login on sessionService", function() { 
     expect(sessionServiceMock.login).toHaveBeenCalledWith("[email protected]", "foobarfoo"); 
    }); 

    describe("when the login is executed", function() { 
     it("if successful, should change state to next_state", function() { 
     deferredLogin.resolve(); 
     $rootScope.$digest(); 
     expect(stateMock.go).toHaveBeenCalledWith("next_state"); 
     }); 

     it("if unsuccessful, should show a popup", function() { 
     deferredLogin.reject(); 
     $rootScope.$digest(); 
     expect(ionicPopupMock.alert).toHaveBeenCalled(); 
     }); 
    }); 
    }); 
}); 

login.controller.js

(function() { 
    var app = angular.module("myApp"); 

    app.controller("LoginController", function($translate, $state, $ionicPopup, $localStorage, sessionService, userService) { 
    var vm = this; 

    vm.email = null; 
    vm.password = null; 

    vm.login = function() { 
     $localStorage.email = vm.email; 
     $localStorage.password = vm.password; 

     sessionService.login().then(
     function(data) { 
      if (userService.isAuthenticated()) { 
      // User is logged, go to the next state 
      $state.go("next_state"); 
      } else { 
      // User is not logged (invalid credentials), show an alert message 
      var alertPopup = $ionicPopup.alert({ 
       title: $translate.instant("LOGIN_FAIL_TITLE"), 
       template: $translate.instant("LOGIN_FAIL_MESSAGE") 
      }); 
      } 
     } 
    ); 
    } 
    }); 
})(); 

login.controller.tests.js:ここで私が使用していたコードです私が見つけたさまざまな解決策は、私はいつも同じ結果を得る:

... 
PhantomJS 2.1.1 (Linux 0.0.0) LoginController #login should call login on sessionService FAILED 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    TypeError: undefined is not an object (evaluating 'sessionServiceMock.login') in unit-tests/controllers/login.controller.tests.js (line 63) 
    unit-tests/controllers/login.controller.tests.js:63:32 
    [email protected]://localhost:9876/context.js:151:17 
PhantomJS 2.1.1 (Linux 0.0.0) LoginController #login when the login is executed if successful, should change state to capture_image FAILED 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    TypeError: undefined is not an object (evaluating 'deferredLogin.resolve') in unit-tests/controllers/login.controller.tests.js (line 68) 
    unit-tests/controllers/login.controller.tests.js:68:22 
    [email protected]://localhost:9876/context.js:151:17 
PhantomJS 2.1.1 (Linux 0.0.0) LoginController #login when the login is executed if unsuccessful, should show a popup FAILED 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:13691:24 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17878:12 
    [email protected]/home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17800:30 
    [email protected]/home/user/NSS/my-app/www/lib/angular-mocks/angular-mocks.js:2922:60 
    [email protected]://localhost:9876/context.js:151:17 
    /home/user/NSS/my-app/www/lib/ionic/js/ionic.bundle.js:17918:53 
    TypeError: undefined is not an object (evaluating 'deferredLogin.reject') in unit-tests/controllers/login.controller.tests.js (line 74) 
    unit-tests/controllers/login.controller.tests.js:74:22 
    [email protected]://localhost:9876/context.js:151:17 
... 

私が間違っていることを理解できません。前もって感謝します。

UPDATE:

マシュー・グリーンは、私はテストが書かれている方法を変更した、言うように。今、彼らは彼の勧告に従うと、私はまた、必要ないくつかのより多くの注射を追加しました:あなたのsessionService.login()は約束を返すべき関数があるように見えます

describe("LoginController", function() { 
    var controller, 
     stateMock, 
     ionicPopupMock, 
     localStorageMock, 
     sessionServiceMockPromise, 
     sessionServiceMock; 

    // Load the application module 
    beforeEach(module("myApp")); 

    // Avoid trying to load all templates of the application 
    beforeEach(module(function($provide, $urlRouterProvider) { 
    $provide.value("$ionicTemplateCache", function() {}); 
    $urlRouterProvider.deferIntercept(); 
    })); 

    // Avoid asynchronous loader of the translations (problem with the angular-translate-design) 
    beforeEach(module(function($provide, $translateProvider) { 
    $provide.factory("customLoader", function($q) { 
     return function() { 
     var deferred = $q.defer(); 
     deferred.resolve({}); 
     return deferred.promise; 
     }; 
    }); 

    $translateProvider.useLoader("customLoader"); 
    })); 

    // Instanciate and initialize the controller and mocks 
    beforeEach(inject(function($controller, $q) { 
    sessionServiceMockPromise = $q.defer(); 
    sessionServiceMock = jasmine.createSpyObj("sessionServiceMock", ["login"]); 
    sessionServiceMock.login.and.callFake(function() { 
     return sessionServiceMockPromise.promise; 
    }); 

    stateMock = jasmine.createSpyObj("$state spy", ["go"]); 

    ionicPopupMock = jasmine.createSpyObj("$ionicPopup spy", ["alert"]); 

    localStorageMock = jasmine.createSpyObj("$localStorage spy", ["getItem"]); 

    controller = $controller("LoginController", { 
     "$state": stateMock, 
     "$ionicPopup": ionicPopupMock, 
     "$localStorage": localStorageMock, 
     "sessionService": sessionServiceMock 
    }); 
    })); 

    describe("#login", function() { 
    beforeEach(inject(function(_$rootScope_) { 
     $rootScope = _$rootScope_; 
     controller.login(); 
     sessionServiceMockPromise.resolve(); 
    })); 

    it("should call login on sessionService", function() { 
     expect(sessionServiceMock.login).toHaveBeenCalledWith(); 
    }); 

    describe("when the login is executed", function() { 
     it("if successfull, should change state to capture_image", inject(function(userService) { 
     spyOn(userService, "isAuthenticated").and.callFake(function() { return true; }); 
     $rootScope.$digest(); 
     expect(stateMock.go).toHaveBeenCalledWith("nextState"); 
     })); 

     it("should show a popup", inject(function(userService) { 
     spyOn(userService, "isAuthenticated").and.callFake(function() { return false; }); 
     $rootScope.$digest(); 
     expect(ionicPopupMock.alert).toHaveBeenCalled(); 
     })); 
    }); 
    }); 
}); 
+0

「未定義はオブジェクトではありません」はここでは意味がありません。 Phantomjsはエラーメッセージを呑み込む傾向があります。他のブラウザ(Chrome)で実行し、エラーを確認してください。 – estus

答えて

1

。そういう場合には、あなたが持っているものにいくつかの問題があります。

まず、このサービスを他のサービスとは異なる設定にする理由はわかりません。これはおそらくあなたの問題の一部である可能性があります。他の人と同じように設定すると、このようなものになります。

var sessionServiceMockPromise = $q.defer(); 
sessionServiceMock = jasmine.createSpyObj('sessionServiceMock', ['login']); 
sessionServiceMock.login.and.callFake(function() { 
    return sessionServiceMockPromise.promise; 
}); 

ここで、ログインは約束を返す関数であることを確認します。 sessionServiceMockPromiseを使用すると、あなたのテストでsessionServiceMockPromise.resolve([data])(またはその点についてはreject())を呼び出して、約束の結果を確認することができます。

第2に、2つの変数を使用してログインを呼び出すことが期待されます。いいえ、サービスやテストのどちらのコードでも、変数を受け入れる関数であることがわかります。より良いテストは、それが呼び出されるか、状態があなたが期待するものに設定されているかもしれません。

関連する問題