用于AngularJS的Karma / Jasmine中的模块依赖性

时间:2015-11-24 09:39:42

标签: angularjs unit-testing mocking karma-jasmine

我正在尝试在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

1 个答案:

答案 0 :(得分:7)

在测试中使用ngSanitize有三种选择:

  1. 将服务注入您的测试
  2. 存根对ngSanitize的方法调用
  3. 模拟整个ngSanitize服务
  4. 您选择的选项实际上取决于在您的工作代码中使用ngSanitize(而不是您的测试代码)。

    无论你选择哪一个,都需要在测试中提供服务,不需要$provider(这包括选项1,如果你只是想要,则不需要做任何事情。将其提供给您的过滤器):

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

    此外,确保所有js文件都被业力挑选并加载。您可以在karma.conf.js中将其添加到files:属性中来定义此内容。

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

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