如何在每个 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.
是否可以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.