gpt4 book ai didi

javascript - 单元测试需要 ngModel 的 Angular 1.5 组件

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:41:47 24 4
gpt4 key购买 nike

要测试 Angular 1.5 组件,如果您不需要测试任何 DOM,文档建议您使用 ngMock 的 $componentController 而不是使用 $compile。

但是,我的组件使用 ngModel,我需要将其传递到 $componentController 的 locals 中,但是无法以编程方式获取 ngModelController;测试它的唯一方法是用它实际 $compile 一个元素,因为这个问题仍然悬而未决:https://github.com/angular/angular.js/issues/7720 .

有什么方法可以在不使用 $compiling 的情况下测试我的组件 Controller 吗?我也不想自己模拟 ngModelController,因为它的行为有点广泛,如果我的测试依赖于一个假的而不是真实的东西,那么新版本的 Angular 可能会破坏它(尽管这可能不是'考虑到 Angular 1 正在逐步淘汰,这不是问题。

最佳答案

tl;dr:解决方案在第三个代码块中。

but there is no way to programmatically get the ngModelController

不是那种态度。 ;)

您可以通过编程方式获取它,只是有点迂回。这样做的方法是in the code for ngMock's $componentController service (此处转述);使用 $injector.get('ngModelDirective') 查找它, Controller 函数将作为 controller 属性附加到它:

this.$get = ['$controller','$injector', '$rootScope', function($controller, $injector, $rootScope) {
return function $componentController(componentName, locals, bindings, ident) {
// get all directives associated to the component name
var directives = $injector.get(componentName + 'Directive');
// look for those directives that are components
var candidateDirectives = directives.filter(function(directiveInfo) {
// ...
});

// ...

// get the info of the component
var directiveInfo = candidateDirectives[0];
// create a scope if needed
locals = locals || {};
locals.$scope = locals.$scope || $rootScope.$new(true);
return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
};
}];

尽管在实例化时需要为 $element$attrs 提供 ngModelController 局部变量。 The test spec for ngModel demonstrates exactly how to do this in its beforeEach call :

beforeEach(inject(function($rootScope, $controller) {
var attrs = {name: 'testAlias', ngModel: 'value'};


parentFormCtrl = {
$$setPending: jasmine.createSpy('$$setPending'),
$setValidity: jasmine.createSpy('$setValidity'),
$setDirty: jasmine.createSpy('$setDirty'),
$$clearControlValidity: noop
};


element = jqLite('<form><input></form>');


scope = $rootScope;
ngModelAccessor = jasmine.createSpy('ngModel accessor');
ctrl = $controller(NgModelController, {
$scope: scope,
$element: element.find('input'),
$attrs: attrs
});


//Assign the mocked parentFormCtrl to the model controller
ctrl.$$parentForm = parentFormCtrl;
}));

因此,根据我们的需要调整它,我们得到这样的规范:

describe('Unit: myComponent', function () {
var $componentController,
$controller,
$injector,
$rootScope;

beforeEach(inject(function (_$componentController_, _$controller_, _$injector_, _$rootScope_) {
$componentController = _$componentController_;
$controller = _$controller_;
$injector = _$injector_;
$rootScope = _$rootScope_;
}));

it('should update its ngModel value accordingly', function () {
var ngModelController,
locals
ngModelInstance,
$ctrl;

locals = {
$scope: $rootScope.$new(),
//think this could be any element, honestly, but matching the component looks better
$element: angular.element('<my-component></my-component>'),
//the value of $attrs.ngModel is exactly what you'd put for ng-model in a template
$attrs: { ngModel: 'value' }
};
locals.$scope.value = null; //this is what'd get passed to ng-model in templates
ngModelController = $injector.get('ngModelDirective')[0].controller;

ngModelInstance = $controller(ngModelController, locals);

$ctrl = $componentController('myComponent', null, { ngModel: ngModelInstance });

$ctrl.doAThingToUpdateTheModel();
scope.$digest();

//Check against both the scope value and the $modelValue, use toBe and toEqual as needed.
expect(ngModelInstance.$modelValue).toBe('some expected value goes here');
expect(locals.$scope.value).toBe('some expected value goes here');
});
});

附录:您还可以通过在 beforeEach 中注入(inject) ngModelDirective 并在 describe block 中设置一个 var 来进一步简化它以包含 Controller 功能,就像您对 $controller 等服务所做的那样。

describe('...', function () {
var ngModelController;

beforeEach(inject(function(_ngModelDirective_) {
ngModelController = _ngModelDirective_[0].controller;
}));
});

关于javascript - 单元测试需要 ngModel 的 Angular 1.5 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43005861/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com