如何在每个 karma/jasmine 测试文件的开头 bootstrap angular?

How to bootstrap angular at the start of each karma/jasmine test file?

是否可以angular bootstrap 将应用程序放在每个测试文件的开头?而不是当前的行为,它在一系列测试的开头有应用 bootstrap,然后在所有测试文件中使用相同的实例(我们现在在 ~60 个文件中有大约 600 个测试)?

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

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

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

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

});

摘自 .

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