使用Angular和Jasmine测试提供程序中的$ log.error

时间:2016-04-27 16:09:35

标签: angularjs

我有一个通过$ log.error()发送错误的模块。这是有效的,我正在尝试完成它的测试。我的问题是我无法验证它在我的规范中记录错误。

Plunkr

代码:

var app = angular.module('plunker', []);

app.provider('MordorProvider', function($logProvider, $injector) {
  // we gotta do this cuz we're a provider and don't have access to $log yet
  var $log = angular.injector(['ng']).get('$log');

  this.makeMeAnErrorWorthyOfMordor = function () {
    $log.error('You shall not pass!');
  }

  this.$get = function () {
    return this;
  };
});

试验:

describe('Gandalfs last stand', function() {

  var MordorProvider,
      $log;

  beforeEach(module('plunker'));

  beforeEach(inject(function(_MordorProvider_, _$log_) {
    MordorProvider = _MordorProvider_;
    $log = _$log_;
  }));

  it('should shout out!', function() {
    MordorProvider.makeMeAnErrorWorthyOfMordor();
    expect($log.error.logs).toContain('You shall not pass!');
  });
});

我知道我的规范是使用ngMock,因此我可以访问$ log.error.logs,但是如果它无法访问相同的$ log数据,我对如何测试它感到困惑。如果您打开该plunkr上的控制台,您可以看到正在发出错误。

2 个答案:

答案 0 :(得分:1)

angular.injector创建一个新的注入器实例,从而创建新的$log服务实例。它不应该在生产中的Angular应用程序中使用,它的有效用例太少了。

app.provider('MordorProvider', function($logProvider, $injector) {
  // we gotta do this cuz we're a provider and don't have access to $log yet
  var $log = angular.injector(['ng']).get('$log');
  ...
});

不能被视为在提供商中使用$log的变通方法。服务提供商无法注入服务实例的原因很简单 - 它们尚未实例化。

在这种情况下,$log变量引用$log个实例,该实例无法在其他地方注入,无法进行测试。这就是规范在$log.error.logs上失败的原因。

此服务中没有任何内容需要provider而不是factory。当$log以正常方式注入和使用时,可以使用

进行安全测试
beforeEach(module('plunker', {
  $log: {
    error: jasmine.createSpy()
  }
}));

...
expect($log.error).toHaveBeenCalledWith('You shall not pass!');

由于$window服务的使用是使$log不适合注入configprovider的唯一因素,因此可以对其进行克隆和修改以避免此限制:

angular.module('uniformLog', []).config(function ($provide, $injector, $logProvider) {
  var uniformLog = $injector.invoke($logProvider.$get, null, { $window: window });
  $provide.constant('uniformLog', uniformLog);
  // or $provide.constant('$log', ...) to override it entirely
});

angular.module('app', ['uniformLog']).config(function ($logProvider, uniformLog) {
  $logProvider.debugEnabled(false);
  uniformLog.debug('...');
});

答案 1 :(得分:0)

你应该只是模拟$ log.error函数并验证它是否被调用

beforeEach(function() {
    spyOn($log, 'error');
}

it('should shout out!', function() {
    MordorProvider.makeMeAnErrorWorthyOfMordor();
    expect($log.error).toHaveBeenCalledWith('You shall not pass!');
});