2016-08-20 4 views
2

$ http.get()でAuthファクトリを介してログインする単純なアプリ(ヨー角ジェネレータ)をやっています。成功した場合、 "sessionId"値は$ localStorageでローカルに設定されます。すべて正常に動作しますが、私はユニットテストで深刻な問題があります。私は何をテストするべきなのか私の心の中で定義することはできません! これは私の状況です。

コントローラ/ logincontrollers.js

angular.module('myApp') 
.controller('LoginCtrl',['$rootScope', '$scope', '$location', '$localStorage', 'Auth', function ($rootScope, $scope, $location, $localStorage, Auth) { 

    Auth.Logout(); 
    $rootScope.loginSucceeded = false; 
    $scope.currentUser = {}; 

    $scope.login = function() { 
    var formData = { 
     username: $scope.username, 
     password: $scope.password 
    }; 

    Auth.Login(formData).then(function (response) { 
     if (response.data.loginSucceeded === true && response.data.sessionId !== null) { 
     $scope.currentUser = {username: $scope.username, sessionId: response.data.sessionId}; 
     $localStorage.currentUser = $scope.currentUser; 
     $rootScope.loginSucceeded = true; 
     window.location = '/'; 
     } else { 
     $scope.error = 'Invalid credentials'; 
     } 
    }, function (response) { 
     $scope.error = 'Connection error'; 
     console.log(response); 
    }); 
    }; 

}]); 

サービス/ auth.js

angular.module('myApp') 
.constant('baseURL', 'http://localhost:8080') 
.factory('Auth',['$http', '$localStorage', 'baseURL', function ($http, $localStorage, baseURL) { 

    return { 
    Login: function (data) { 
     return $http.get(baseURL + '/login', { 
     params: data 
     }); 
    }, 
    Logout: function() { 
     delete $localStorage.currentUser; 
    } 
    }; 

}]); 

サーバーは、クエリを使ってログイン要求を受け入れ

http://localhost:8080/login?username=Test&password=Test 

そして今、重要なポイントをparamsは。 これは私が誤りなくテストしたものです。

テスト/仕様/ logincontroller.js

describe('Controller: LoginCtrl', function() { 

    // load the controller's module 
    beforeEach(module('myApp')); 

    var scope, $httpBackend, LoginCtrl; 

    // Initialize the controller and a mock scope 
    beforeEach(inject(function ($rootScope, _$httpBackend_, $controller, Auth) { 
    $httpBackend = _$httpBackend_; 
    scope = $rootScope.$new(); 
    LoginCtrl = $controller('LoginCtrl', { 
     $scope: scope, Auth: Auth 
     // place here mocked dependencies 
    }); 
    })); 
    afterEach(function() { 
    $httpBackend.verifyNoOutstandingExpectation(); 
    $httpBackend.verifyNoOutstandingRequest(); 
    }); 


    it('should fetch sessionId', function() { 
    $httpBackend.when('GET', 'http://localhost:8080/login', {params: {username: "Test", password: "Test"}}) 
    .respond({"sessionId":"c4b0b46a04b54247ac27f3bd4db289a0","loginSucceeded":true}); 
    scope.login(); 
    $httpBackend.flush(); 
    }); 

}); 

私はエラーを私に恩返しやろう他のすべての事。 このテストが良いかどうか、私は何をテストすべきか理解してもらえますか?たぶん、フォーム、または$ localStorageまたは何ですか? あなたに私に示唆するための深刻なユニットテストのマニュアル/リソース/ベストプラクティスがありますか?

アドバイスありがとうございます。

--- UPDATE ---

You can explain why if i do this test: 

it('should fetch sessionId', function() { 
    $httpBackend.when('GET', 'http://localhost:8080/login', {params: {username: "Test", password: "Test"}}) 
    .respond({sessionId:"c4b0b46a04b54247ac27f3bd4db289a0",loginSucceeded:true}); 
    scope.login(); 
    expect(scope.sessionId).toEqual('c4b0b46a04b54247ac27f3bd4db289a0'); 
    $httpBackend.flush(); 
    }); 

私はこのエラーを得た:テストに関する親指の

PhantomJS 2.1.1 (Mac OS X 0.0.0) Controller: LoginCtrl should fetch sessionId FAILED 
     Expected undefined to equal 'c4b0b46a04b54247ac27f3bd4db289a0'. 
     test/spec/controllers/logincontroller.js:44:36 
     [email protected]://localhost:8081/context.js:151:17 
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 5 of 5 (1 FAILED) (0.008 secs/0.063 secs) 
+0

あなたのテストは私には良いです。私はコントローラの代わりに工場をテストすることを提案することができます – hpfs

答えて

1

私の一般的なルールは、あなたがテストしているものを、この

  • テストですのみ。あなたのコントローラをテストしている場合は、これだけをテストしてください
  • この目的のために他のものを模倣してください。あなたの場合、これは認証サービスになります。

authサービスを個別にテストし、同様のパターンに従って$ httpサービスなどを模擬します。

私は100万マイル離れているわけではなく、2つの異なるテストスイート(ファイル)に分割していると思います。

賢明なのモック

私は私が必要とする機能に空のオブジェクト、その後spyを作成し、データのリターンを模擬するために$provideを使用する傾向があります。そうすれば、何が呼び出されているのか、どのデータが返されるのか正確に知ることができます。

この例は次のようになります。

module(function($provide) { 
    $provide.service('Auth', function() { 
    this.logIn = jasmine.createSpy('logIn').andCallFake(function(params) { 
     //a fake implementation 
    }); 
    this.logOut = jasmine.createSpy('logOut').andCallFake(function(params) { 
     //a fake implementation 
    }); 
    }); 
}); 

これの美しさは、あなたが/主張する機能あなたはまた、より高度な操作を行うことができますので、

expect(Auth.LogIn).toHaveBeenCalled(); 

のように呼ばれてきた期待できるということです特定のパラメータで呼び出されたことを確認するようなもの。これについて簡単にアクセス可能なコンテンツがたくさんあります。あなたは今何を探すべきかを知ることができます。

上記のコードは手書きであるため、若干の誤差がある可能性があります。これは、Jasmine v2で何ができるのかを示すgood websiteです。

+0

あなたの助言に感謝します。あなたは「他のすべてを模倣する」ためにより明示的になりますか?私の場合、Authサービスを実際にどのように模擬すべきですか?私に例を教えてください。ありがとうございました –

+0

@AlessioMasucci私の更新をチェックしてください! – Chris

関連する問題