javascript - 如何在每个 karma/ Jasmine 测试文件的开头引导 Angular ?

标签 javascript angularjs unit-testing karma-jasmine

是否可以在每个测试文件的开头对应用程序进行 Angular 引导?而不是当前行为,即在一系列测试开始时使用应用程序 Bootstrap ,然后在所有测试文件中使用相同的实例(我们现在在 ~60 个文件中有大约 600 个测试)?

我们有 beforeEach 语句来处理清理,但这无济于事。事实上,似乎有时 beforeEach 语句会无缘无故地被完全跳过(测试运行器可能存在内存泄漏)。

所以我想采取的方法是让每个测试文件引导 Angular 应用程序,以便完全重置状态,而不是重复使用由不同测试设置状态的依赖注入(inject)(即服务)。

最佳答案

您无需为测试引导应用程序。这就是为什么我们有 angular-mock。使用 angular.module('app.module') 我们加载测试所需的模块,该模块包含我们要测试的组件。由于 angular-mock 不是内存泄漏的原因,因此可能有多种原因。内存泄漏最常见的原因之一是 jasmine 本身以及我们通常编写测试的方式。我们用于在测试中注入(inject)的依赖项的变量是在 describe 范围内定义的,并且在测试完成时不能被 GC 收集。这是因为 it block 中存在对这些变量的引用,这些变量无法被垃圾回收,因为这些变量仍然存在于测试树的某些其他范围内。另一个问题可能是在每次测试后也应该清理的编译元素。因此,您可能需要清理以下内容:

  • compiled element when using $compile for testing directives
  • all variables in the describe functions scope

你可以这样做:

describe('testSuite', function () {
    var suite = {};

    beforeEach(module('app'));

    beforeEach(inject(function ($rootScope, $compile, heavyLoad) {
      suite.$rootScope = $rootScope;
      suite.$compile = $compile;
      suite.heavyLoad = heavyLoad;
      suite.$scope = $rootScope.$new();

      spyOn(suite.heavyLoad, 'getHeavyString').and.callThrough();
      spyOn(suite.heavyLoad, 'getHeavyObject').and.callThrough();
      spyOn(suite.heavyLoad, 'getHeavyList').and.callThrough();
    }));

    // NOTE: cleanup
    afterEach(function () {
      // NOTE: prevents DOM elements leak
      suite.element.remove();
    });
    afterAll(function () {
      // NOTE: prevents memory leaks because of JavaScript closures created for 
      // jasmine syntax (beforeEach, afterEach, beforeAll, afterAll, it..).
      suite = null;
    });

    suite.compileDirective = function (template) {
      suite.element = suite.$compile(template)(suite.$scope);
      suite.directiveScope = suite.element.isolateScope();
      suite.directiveController = suite.element.controller('heavyLoad');
    };

    it('should compile correctly', function () {
      // given
      var givenTemplate = '<div heavy-load></div>';

      // when
      suite.compileDirective(givenTemplate);

      // then
      expect(suite.directiveScope.title).toBeDefined();
      expect(suite.directiveScope.items).toBeDefined();
      expect(suite.heavyLoad.getHeavyString).toHaveBeenCalled();
      expect(suite.heavyLoad.getHeavyList).toHaveBeenCalled();
    });

});

取自here .

这应该会显着减少内存泄漏。 你还应该看看你的模块结构和你的模块的依赖图,因为你可能有一些测试不需要的模块,但它们无论如何都会被加载。它们可能占用大量内存或包含内存泄漏,可能会给您带来额外的问题。 你也可以看看this github project .

关于javascript - 如何在每个 karma/ Jasmine 测试文件的开头引导 Angular ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33045780/

相关文章:

Javascript onclick 将文本放入文本字​​段

javascript - 从 php 返回的表未使用 jquery 添加到给定的 div

javascript - VueJS 数据库操作后刷新内容

javascript - Protractor 本地和全局安装的行为不同

angularjs - 在 ng-repeat 中使用相同的值初始化单选按钮

angularjs - Karma 找不到模块 'optimist'

javascript - 使用 karma 测试 angularjs 时初始化 Controller 时出错

asp.net-mvc-3 - 单元测试使用 NHibernate 的 MVC Controller ,实现和不实现存储库模式

unit-testing - Spock 与 DbUnit 测试用例缓慢

javascript - 使用 JavaScript 获取通过 HTML 文件选择器按钮选择的文件的绝对路径