单元测试控制器与 AngularJS 中的表单一样
Unit testing ControllerAs with forms in AngularJS
我对Angular有以下情况:
Controller
function Controller () {
// form used in template
this.form ...
}
具有窗体并使用此控制器的模板
Template
<div ng-controller="Controller as ctrl">
<form name="ctrl.form">
...
</div>
我不得不说,我总体上很困惑为什么 Angular 除了自动添加 this.form
或 $scope.form
之外没有更好的方法将表单添加到控制器,具体取决于您使用控制器的方式,但我想这是另一个问题。
我现在面临的真正问题是我不确定应该如何测试它。如果我只是在测试中实例化控制器,那么我的表单是未定义的
$controller('Controller as ctrl')
我确实找到了一种方法,只需编译模板
$scope = $rootScope.$new();
$compile(template)($scope);
但是由于模板中的ng-controller
启动了新作用域,因此我无法使用$scope.ctrl
直接访问控制器,而是必须执行类似$scope.$$childHead.login
。我觉得它变得太复杂了。编辑:更不用说$$表示"私有"财产。
我自己已经解决了,但我把它留在这里不被接受,因为我认为这个解决方案不是很好。如果有人知道更好的方法,请发布。
编译模板的问题在于,也不可能在控制器中插入模拟服务,至少我没有弄清楚。您在$scope上得到一个控制器实例,例如$scope.ctrl
,但仅此而已。
第二次尝试是在模板中仅找到表单,编译并将其添加到单独实例化的控制器中。这有效,但不是真的,因为窗体和控制器的$scope不同,因此对字段的任何更新都不会反映控制器状态。
它最终的工作方式是使用$scope实例化控制器
ctrl = $controller('Controller as ctrl', {
someDependency: mockDependency,
$scope: $scope
});
然后使用相同的$scope编译部分模板(只是表单)
var formTpl = angular.element(template).find('form');
form = $compile(formTpl)($scope);
这样,控制器最终会出现 $scope.ctrl
,但由于表单已经命名name="ctrl.form"
因此它入到$scope.ctrl.form
中并且在控制器中可见。
使用 controllerAs
时,您可以在测试中访问您的表单,如下所示:
// 1. Create a new scope
var $scope = $rootScope.$new();
// 2. Run the controller
var Controller = $controller("Controller as ctrl", { $scope: $scope });
// 3. Compile the template against our scope
// This will add property $scope.ctrl.form (assuming that form has name="ctrl.form")
$compile(angular.element(templateHtml))($scope);
// 4. Controller.form should now also be defined
expect(Controller.form).toBeDefined();
同时,模拟可以通过使用Angular的$provide来实现:
beforeEach(angular.mock.module(function ($provide) {
function ApiServiceMock() {
this.getName() = function () {
return "Fake Name";
};
}
// Provide our mocked service instead of 'ApiService'
// when our controller's code requests to inject it
$provide.value("ApiService", ApiServiceMock);
}));
完整示例(同时使用两者 - 使用控制器 A 进行模拟和表单编译):
主要应用代码:
angular.module("my.module", [])
.service("ApiService", function () {
this.getName = function () {
return "Real Name";
};
})
.controller("Controller", function (ApiService) {
var ctrl = this;
ctrl.someProperty = ApiService.getName();
});
.HTML:
<div ng-controller="Controller as ctrl">
<form name="ctrl.form">
<input type="email" name="email" />
</form>
</div>
测试:
describe("Controller", function () {
var $scope,
Controller;
beforeEach(angular.mock.module("my.module"));
beforeEach(angular.mock.module(function ($provide) {
function ApiServiceMock() {
this.getName() = function () {
return "Fake Name";
};
}
$provide.value("ApiService", ApiServiceMock);
}));
beforeEach(inject(function ($rootScope, $controller, $compile) {
$scope = $rootScope.$new();
Controller = $controller("Controller as ctrl", { $scope: $scope });
// FIXME: Use your own method of retrieving template's HTML instead 'getTemplateContents' placeholder
var html = getTemplateContents("./my.template.html"),
formTpl = angular.element(html).find('form');
$compile(formTpl)($scope);
}));
it('should contain someProperty', function () {
expect(Controller.someProperty).toBeDefined();
});
it('form should contain an email field', function () {
expect(Controller.form.email).toBeDefined();
});
});
- 可以't让我的if语句处理js中的html表单输入
- 如何使用WCF服务和javascript表单post上传.doc文件
- Javascript生成的表单未提交
- 如何使用javascript或html下载PDF格式的填写表单
- HTML表单提交时未执行外部函数
- 如何将输入(type=text)从html表单传递到javascript函数
- 通过单击表单中的按钮,在代码生成中使用javascript生成字母数字代码
- Ajax发布表单序列化,发布引号'
- 多级HTML表单
- 后焦点更改为IE 11中的地址栏,而不是转移到表单中的下一个控件
- 在验证和发送邮件后更改联系人表单的 html
- Jquery/javascript方式发送50个表单,就像发送1个表单一样
- 如何将 Base64 字符串转换为 javascript 文件对象,就像从文件输入表单一样
- 后退按钮也像提交按钮一样验证html表单
- 使用AngularJS让+键像Tab键一样在表单中工作
- HTML链接,它会像表单一样下拉菜单
- 表单像ajax一样提交'It’不起作用
- 单元测试控制器与 AngularJS 中的表单一样
- 向表中插入数据并像表单一样提交
- 当文本字段发生变化时,检查表单的有效性,就像gmail注册表单一样