13

私はyeomanジェネレーターで作成されたアプリを使用しており、カルマでテストを行っています。

すべてのサービスに再利用可能なモック オブジェクトがあります。特定のサービスの依存関係をモックに正しく置き換えるにはどうすればよいですか。そうすれば、ジャスミンを使用してメソッドをスパイできます

これまでのところ、私はこのようにしています:

私のサービス:

angular.module('ql')
  .service('loginService', ['$http','API','authService', function ($http, API, authService) {
    return {
      //service implementation
    }]);

authService のモック:

'use strict';
//lets mock http auth  service, so it would be spied upon.
ql.mock.$authServiceMockProvider = function() {
  this.$get = function() {
    var $service = {
      loginConfirmed: function() { }
    };
    return $service;
  };
};

//and register it.
angular.module('qlMock').provider({
  $authServiceMock: ql.mock.$authServiceMockProvider
});

そして私のテスト:

'use strict';

describe('When i call login method()', function () {

  // load the service's module
  beforeEach(module('ql'));
  beforeEach(angular.mock.module('qlMock'));

  // instantiate service
  var loginService,
  authService,
  $httpBackend;
  beforeEach(function() {
    // replace auth service with a mock.
    // this seems kind of dirty... is there a bettery way? 
    module(function($provide, $injector){
      authService = $injector.get('$authServiceMockProvider').$get();
      $provide.value('authService', authService);
    });

    //actually get the loginService
    /*jshint camelcase: false */
    inject(function(_loginService_, _$httpBackend_) {
      loginService = _loginService_;
      $httpBackend =_$httpBackend_;
    });

    //http auth module method, that should be call only on success scenarios
    spyOn(authService, 'loginConfirmed').andCallThrough();
  });
  it('it should do something', function () {
  //actual test logic
  });
});

私が気に入らないのは次の行です:

authService = $injector.get('$authServiceMockProvider').$get();

何らかの方法で authServiceMock を取得し (プロバイダーを取得せずに et メソッドを呼び出す)、それを loginService に挿入したいと考えています。

$authServiceMock を単純に authService と呼び、それをモックとして提供して、デフォルトの実装を常にオーバーライドできることは知っていますが、これを行いたくありません。

4

3 に答える 3

15

これが遅れていることはわかっていますが、この投稿に遭遇した人を助けるかもしれません.

Jasmine でのサービスのモックは、Angular の$provideサービスを使用して非常に簡単です。秘訣は、サービスを注入する前に $provide を使用してサービスの実装を交換することです。

たとえば、$locationサービスを使用して現在の URL に関する情報を取得するサービスをテストしているとします。

// load the service's module under test
beforeEach(module('myExampleModule'));

// mock out $location with a fake one
beforeEach(module(function ($provide) {

   //create mock impl
     var mockLocation = {
         path: function(){
                 return '/somewhere'
                 }
              }

$provide.value('$location', mockLocation); // use $provide to swap the real $location with our mock
}));

var $location;
// inject dependencies ($location will be our mocked $location)
beforeEach(inject(function (_$location_) {
 $location = _$location_;
}));

it('should return mock url', function(){
      var path = $location.path();
      expect(path).toBe('/somewhere'); //Assert that $location.path() returns '/somewhere'
});
于 2014-07-10T18:25:20.393 に答える
0

サービス内でサービスを単体テストしたことはありません。

loginService の単体テストを行っているため、サービスが AuthService によって提供されたデータと対話する方法にのみ関心があり、AuthService が正しく機能していることには関心がありません。これは、モックで設定したものです。

これが私のアプローチだと思います:(親の記述内)

  var   
     loginService, 
     authService
     AUTH_DATA
  ;

  beforeEach(function() {
     module('ql');
     // I am assuming this is the global app module so both services live here? If not include this module as well
  });


   beforeEach(inject(function (_authService_, _loginService_) {
      authService = _authService_;
      loginService = _loginService_;
      //Now with the spy setup you intercept the calls to the service and you choose what data to return, based on the unit test. Now your LoginService can simply resond to the data it is give from the login service
    }));

  it('it should do something', function () {
     spyOn(authService, 'loginConfirmed').andReturn(AUTH_DATA);
     loginService.confirmLogin(); //Dont know your actual API but a contrived guess
     expect('something to happen in loginservice when AUTH_DATA is returned').toBe('Something else')
   });
于 2014-03-24T06:33:36.497 に答える