使用bootstrap ui对话框对Angular js进行单元测试
Unit Testing Angular js with bootstrap-ui dialog
我很难理解如何使用jasmine来单元测试angularjs中bootstrap ui对话框元素的创建。控制器:
MyModule.controller('BaseCtrl', ['$scope', '$routeParams', '$location', '$http', '$filter', '$data', '$locationParse', '$dialog', function ($scope, $routeParams, $location, $http, $filter, $data, $locationParse, $dialog) {
//[...Loads of other stuff...]
//method in question:
$scope.delete = function() {
var boxResult;
if ($scope.record._id) {
var msgBox = $dialog.messageBox('Delete Item', 'Are you sure you want to delete this record?', [{
label: 'Yes',
result: 'yes'
}, {
label: 'No',
result: 'no'
}]);
msgBox.open()
.then(function(result) {
if (result === 'yes') {
$http.delete('api/' + $scope.modelName + '/' + $scope.id).success(function() {
if (typeof $scope.dataEventFunctions.onAfterDelete === "function") {
$scope.dataEventFunctions.onAfterDelete(master);
}
$location.path('/' + $scope.modelName);
});
}
if (result === 'no') {
boxResult = result;
};
});
//can't close the msxBox from within itself as it breaks it. OK for now. TODO Refactor.
if (boxResult === 'no') {
msgBox.close();
}
}
}
}]);
测试对象:
describe('"BaseCtrl"', function(){
var $httpBackend;
beforeEach(function() {
angular.mock.module('MyModule');
});
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
describe('deletion confirmation modal', function() {
var $scope, ctrl, $dialog, fakeDialog;
beforeEach(function() {
inject(function(_$httpBackend_, $rootScope, $routeParams, $controller, $location, _$dialog_){
$dialog = _$dialog_;
fakeDialog = function (title, msg, btns) {
return {
open: function () {
return {
then: function (callback) {
callback('ok'); // 'ok' will be set to param result
}
}
}
}
};
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('api/schema/collection').respond({"email":{"enumValues":[],"regExp":null,"path":"email","instance":"String","validators":[],"setters":[],"getters":[],"options":{"form":{"directive":"email-field"}},"_index":null,"$conditionalHandlers":{}}});
$location.$$path = '/collection/new';
$scope = $rootScope.$new();
ctrl = $controller("BaseCtrl", {$scope: $scope, $dialog: $dialog});
$httpBackend.flush();
spyOn($dialog, 'messageBox').andReturn(fakeDialog);
});
});
it('should inject bootstrap-ui dialog controller', function() {
expect($dialog).toBeDefined();
});
it('should be displayed when $scope.delete() is called', function() {
$scope.record._id = 1;
$scope.delete();
// console.log(dialog.messageBox);
// expect(dialog.open).toHaveBeenCalled();
});
});
});
我得到错误:
PhantomJS 1.9 (Mac) "BaseCtrl" deletion confirmation modal should be displayed when $scope.delete() is called FAILED
TypeError: 'undefined' is not a function (evaluating 'msgBox.open()')
at /Users/steveclements/work/live/forms-angular/app/js/controllers/base.js:632
at /Users/steveclements/work/live/forms-angular/test/unit/baseControllerSpec.js:735
如果我删除fakeDialog方法(和其他相关的测试代码),我会得到错误:
PhantomJS 1.9 (Mac) "BaseCtrl" deletion confirmation modal should be displayed when $scope.delete() is called FAILED
TypeError: 'undefined' is not an object (evaluating 'msgBox.open')
at /Users/steveclements/work/live/forms-angular/app/js/controllers/base.js:632
at /Users/steveclements/work/live/forms-angular/test/unit/baseControllerSpec.js:735
区别在于"msgBox.open"answers"msgBox.open()",所以我不认为mock是问题所在。我读了很多关于其他SO与此相关的答案,但看不出我错在哪里。
我将测试代码更改为:
describe('deletion confirmation modal', function() {
var $scope, ctrl, $dialog, fakeDialog, provider, resolveCallback;
//this fake object replaces the actual dialog object, as the functions are not visible to the test runner.
fakeDialog = {
isOpen: false,
open: function() {
fakeDialog.isOpen = true;
return {
then: resolveCallback
};
},
close: function() {
return true;
}
};
resolveCallback = function(callback) {
}
beforeEach(function() {
module(function($dialogProvider) {
provider = $dialogProvider;
});
inject(function(_$httpBackend_, $rootScope, $routeParams, $controller, $location, _$dialog_) {
$dialog = _$dialog_;
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('api/schema/collection').respond({
"email": {
"enumValues": [],
"regExp": null,
"path": "email",
"instance": "String",
"validators": [],
"setters": [],
"getters": [],
"options": {
"form": {
"directive": "email-field"
}
},
"_index": null,
"$conditionalHandlers": {}
}
});
$location.$$path = '/collection/new';
$scope = $rootScope.$new();
ctrl = $controller("BaseCtrl", {
$scope: $scope,
$dialog: $dialog
});
$httpBackend.flush();
spyOn($dialog, 'messageBox').andReturn(fakeDialog);
$scope.record._id = 1;
});
});
it('provider service should be injected', function() {
expect(provider).toBeDefined();
});
it('dialog service should be injected', function() {
expect($dialog).toBeDefined();
});
it('dialog messageBox should be defined', function() {
$scope.delete();
expect($dialog.messageBox).toHaveBeenCalled();
});
it('should be displayed when $scope.delete() is called', function() {
$scope.delete();
expect(fakeDialog.isOpen).toEqual(true);
});
});
相关文章:
- 在node.js中编写单元测试的最佳方式是什么
- 使用Node.js在应用程序引擎上进行本地单元测试
- 我应该如何衡量JS的单元测试覆盖率?我可以'我对jscoverage不满意
- 在http服务单元测试中使用request-js时,chai.request不是一个函数
- 如何用mocha和rewire模拟node.js单元测试中的Q方法
- Angular js单元测试模拟文档
- Angular.js中的控制器单元测试
- 是否可以在 js 中为单元测试超时
- VS 2015与Gulp JS单元测试的集成
- 节点.js单元测试:测试fs模块抛出错误时的行为
- node.js单元测试mock依赖关系
- 在mochajavascript node.js单元测试框架中,没有从chai.post请求中得到响应
- Angular.js单元测试不调用$animate.enter回调
- JS单元测试用不同的参数运行多次
- Node.js单元测试
- Angular.js单元测试expectPUT
- Angular.js单元测试指令
- JS单元测试,而不必将整个HTML复制到单元测试中
- 在我的Angular JS单元测试中,我应该在什么时候使用$provide和Jasmine Spies
- 使用Jasmine进行JS单元测试