【问题标题】:Mocking Module Dependencies in Karma/Jasmine for AngularJS在 Karma/Jasmine 中为 AngularJS 模拟模块依赖
【发布时间】:2016-02-26 16:24:17
【问题描述】:

我正在尝试在 Karma/Jasmine 中为我项目中的特定模块编写一些单元测试,destination-filters

模块声明:

angular.module('destination-filter', ['ngSanitize']);

除非我将 ngSanitize 作为依赖项删除,否则我的测试将失败。据我了解,这是因为当模块被实例化时,它会尝试引入该依赖项,但因为在我的 spec.js 文件中我没有声明该模块失败。

规格文件:

describe('Destination Filter Controller', function () {

  // Set the variables
  var $controller;
  var mockNgSanitize;

  beforeEach(module('destination-filter'));

  beforeEach(function() {
      module(function($provide) {
          $provide.value('ngSanitize', mockNgSanitize);
      });
  });

  beforeEach(inject(function (_$controller_) {
      $controller = _$controller_('DestinationFilterController');
  }));

  it('should expect the controller to not be null', function() {
      // Check the controller is set
      expect($controller).not.toBeNull();
  });

});

以前,在模拟服务或函数时,$provide 方法已被证明非常有用,但我不确定我在这里的使用是否正确。我假设以这种方式使用的$provide 不能模拟整个模块,而是模拟服务?

为了澄清,如果我从我的模块减速中删除 ...['ngSantize'])...,测试会正确实例化。我收到的错误是Error: [$injector:modulerr] destination-filter

【问题讨论】:

  • 你的业力配置是否加载angular-sanitize.js文件?
  • 它没有。我有点害怕开始在其中添加单独的文件。我知道这就是它的用途,但我真的不想开始在其中放置大量文件。除非您认为这样做可能足够公平。这是标准做法吗?
  • 您需要在代码中包含您使用的 JS 文件,这样才能运行测试。这只是一个角度依赖。我不明白为什么不将它包含在测试中。
  • 是的,成功了,干杯。
  • @yarons,你拯救了我的一天

标签: angularjs unit-testing mocking karma-jasmine


【解决方案1】:

在测试中使用 ngSanitize 时,您可以采取三种选择:

  1. 将服务注入您的测试
  2. 对 ngSanitize 的方法调用存根
  3. 模拟整个 ngSanitize 服务

您选择的选项实际上取决于在您的工作代码(而不是您的测试代码)中使用 ngSanitize。

无论您选择哪一个,您都需要在您的测试中提供该服务,不需要$provider(这涵盖了选项 1,如果您只想这样做,则无需执行更多操作可用于您的过滤器):

beforeEach(module('ngSanitize'));    

beforeEach(inject(function(_ngSanitize_) { // the underscores are needed
    mockNgSanitize = _ngSanitize_;
}));

另外,请确保所有 js 文件都被 karma 拾取和加载。您可以通过将它们添加到 files: 属性来在 karma.conf.js 中定义它。

2。在服务上存根方法

我喜欢存根,并且发现它们在编写测试时非常有用。您的测试应该只测试一件事,在您的情况下是一个过滤器。存根使您可以更好地控制测试,并允许您隔离被测事物。

通常过滤器、控制器、任何东西都需要很多其他东西(服务或工厂,如 $http 或 ngSanitize)。

假设您的过滤器正在使用 ngSanitize 的 $sanitize 清理某些 html,您可以删除该方法以返回您定义的已清理的 html,以针对您的期望进行测试:

// in a beforeEach

spyOn(mockNgSanitize, "$sanitize").and.returnValue('<some>sanitized<html>');

mockNgSanitized.$sanitize(yourDirtyHtml);

See the jasmine docs 了解更多信息。

您可能不得不尝试监视正确的服务,但这应该没问题。

3。模拟整个服务

我不认为你想使用这个选项,因为它会让你发疯,弄清楚什么需要模拟,而且模拟会产生不切实际的期望,而且对你的用例不是特别有用。如果您真的想尝试一下,那么类似下面的内容正朝着正确的方向前进(再次see the jasmine docs

beforeEach(function() {
    mockNgSanitize = ('ngSanitize', ['linky', '$sanitize', '$sanitizeProvider'];
});

it('mocks the ngSanitize service', function() {
    expect(mockNgSanitize.linky).toBeDefined(); 
});

注意:在上面的所有代码中,请确保您继续在描述块的顶部声明任何变量。

【讨论】:

  • 感谢您的完整回答。方法一立即奏效,但这些其他方法对我的测试的其他部分非常有帮助,非常感谢!
猜你喜欢
  • 2013-07-07
  • 2013-12-20
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
相关资源
最近更新 更多