AngularJS -如何正确地用mock替换服务依赖

ccgok5k5  于 2023-11-16  发布在  Angular
关注(0)|答案(3)|浏览(126)

我使用约曼发电机创建的应用程序,并在业力做我的测试。
我的每个服务都有可重用的mock对象。我如何正确地用mock替换特定的服务依赖关系,这样我就可以使用jasmine来监视方法
到目前为止,我是这样做的:
我的服务:

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(不获取provider,也不调用et方法),然后将其注入loginService。
我知道我可以简单地调用我的$authServiceMock authService,并将其作为mock提供,这样它就可以始终覆盖我的默认实现,但我不想这样做。

brtdzjyr

brtdzjyr1#

我知道这已经很晚了,但也许这会帮助那些碰巧看到这篇文章的人。
在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';
      }
    };

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

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();

  //Assert that $location.path() returns '/somewhere'
  expect(path).toBe('/somewhere');
});

字符串

6jygbczu

6jygbczu2#

我想我会简单地使用一个有Angular 的服务装饰器来模拟或完全替换您的服务进行测试。Here is an example

e4yzc0pl

e4yzc0pl3#

我从来没有在一个服务中对一个服务进行过单元测试,至少现在还没有,但是我们的认证/登录功能很快就会出现。
当你对loginService进行单元测试时,你只对服务与AuthService提供的数据交互的方式感兴趣,而不是AuthService是否正确工作。这是你在mock中设置的。
我认为这将是我的方法:(在父母描述)

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')
   });

字符串

相关问题