单元测试 angular-bootstrap $modal [英] Unit testing angular-bootstrap $modal
问题描述
我在尝试为 Angular-Bootstrap $modal
编写 jasmine 单元测试时遇到问题.确切的错误是预期的 spy open 已被调用 [ { templateUrl : '/n/views/consent.html', controller : 'W2ConsentModal as w2modal', resolve : { employee : Function }, size : 'lg' } ] 但是实际调用是 [ { templateUrl : '/n/views/consent.html', controller : 'W2ConsentModal as w2modal', resolve : { employee : Function }, size : 'lg' } ]
I'm having problems trying to write a jasmine unit test for an Angular-Bootstrap $modal
. The exact error is
Expected spy open to have been called with [ { templateUrl : '/n/views/consent.html', controller : 'W2ConsentModal as w2modal', resolve : { employee : Function }, size : 'lg' } ] but actual calls were [ { templateUrl : '/n/views/consent.html', controller : 'W2ConsentModal as w2modal', resolve : { employee : Function }, size : 'lg' } ]
预期的和实际的模态选项对象是相同的.这是怎么回事?
The expected and actual modal options object are the same. What is going on?
(function () {
'use strict';
angular
.module('app')
.controller('W2History', W2History);
W2History.$inject = ['$scope', '$modal', 'w2Service'];
function W2History($scope, $modal, w2Service) {
/* jshint validthis:true */
var vm = this;
vm.showModal = showModal;
function showModal(employee) {
var modalInstance = $modal.open({
templateUrl: '/n/views/consent.html',
controller: 'W2ConsentModal as w2modal',
resolve: {
employee: function () {
return employee;
}
},
size: 'lg'
});
modalInstance.result.then(function (didConsent) {
// code omitted
});
}
}
})();
测试
describe('W2History controller', function () {
var controller, scope, modal;
var fakeModal = {
result: {
then: function (confirmCallback, cancelCallback) {
//Store the callbacks for later when the user clicks on the OK or Cancel button of the dialog
this.confirmCallBack = confirmCallback;
this.cancelCallback = cancelCallback;
}
},
close: function (item) {
//The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
this.result.confirmCallBack(item);
},
dismiss: function (type) {
//The user clicked cancel on the modal dialog, call the stored cancel callback
this.result.cancelCallback(type);
}
};
var modalOptions = {
templateUrl: '/n/views/consent.html',
controller: 'W2ConsentModal as w2modal',
resolve: {
employee: function () {
return employee;
}
},
size: 'lg'
};
beforeEach(function () {
module('app');
inject(function (_$controller_, _$rootScope_, _$modal_) {
scope = _$rootScope_.$new();
modal = _$modal_;
spyOn(modal, 'open').and.returnValue(fakeModal);
controller = _$controller_('W2History', {
$scope: scope,
$modal: modal,
w2Service: w2Srvc
});
});
});
it('Should correctly show the W2 consent modal', function () {
var employee = terminatedaccessMocks.getCurrentUserInfo();
controller.showModal(employee);
expect(modal.open).toHaveBeenCalledWith(modalOptions);
});
});
推荐答案
试试这个:
describe('W2History controller', function () {
var controller, scope, modal;
var fakeModal = {
result: {
then: function (confirmCallback, cancelCallback) {
//Store the callbacks for later when the user clicks on the OK or Cancel button of the dialog
this.confirmCallBack = confirmCallback;
this.cancelCallback = cancelCallback;
}
},
close: function (item) {
//The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
this.result.confirmCallBack(item);
},
dismiss: function (type) {
//The user clicked cancel on the modal dialog, call the stored cancel callback
this.result.cancelCallback(type);
}
};
var modalOptions = {
templateUrl: '/n/views/consent.html',
controller: 'W2ConsentModal as w2modal',
resolve: {
employee: jasmine.any(Function)
},
size: 'lg'
};
var actualOptions;
beforeEach(function () {
module('plunker');
inject(function (_$controller_, _$rootScope_, _$modal_) {
scope = _$rootScope_.$new();
modal = _$modal_;
spyOn(modal, 'open').and.callFake(function(options){
actualOptions = options;
return fakeModal;
});
controller = _$controller_('W2History', {
$scope: scope,
$modal: modal
});
});
});
it('Should correctly show the W2 consent modal', function () {
var employee = { name : "test"};
controller.showModal(employee);
expect(modal.open).toHaveBeenCalledWith(modalOptions);
expect(actualOptions.resolve.employee()).toEqual(employee);
});
});
说明:
我们不应该期望实际的 resolve.employee
与假的 resolve.employee
相同,因为 resolve.employee
是一个函数它返回一个员工(在这种情况下,该员工在关闭中被捕获).函数可能相同,但在运行时返回的对象可能不同.
We should not expect the actual resolve.employee
to be the same with the fake resolve.employee
because resolve.employee
is a function which returns an employee (in this case the employee is captured in closure). The function could be the same but at runtime the returned objects could be different.
您的测试失败的原因是 javascript 比较函数的方式.看看这个 fiddle.无论如何,我不在乎这个,因为我们不应该期待函数实现.在这种情况下,我们真正关心的是 resolve.employee
返回的对象与我们传入的对象相同:
The reason your test is failing is the way javascript compares functions. Take a look at this fiddle. Anyway, I don't care about this because we should not expect function implementations. What we do care about in this case is the resolve.employee
returns the same object as we pass in:
expect(actualOptions.resolve.employee()).toEqual(employee);
所以这里的解决方案是:我们期待除了 resolve.employee
之外的一切:
So the solution here is:
We expect everything except for the resolve.employee
:
var modalOptions = {
templateUrl: '/n/views/consent.html',
controller: 'W2ConsentModal as w2modal',
resolve: {
employee: jasmine.any(Function) //don't care about the function as we check it separately.
},
size: 'lg'
};
expect(modal.open).toHaveBeenCalledWith(modalOptions);
先捕获resolve.employee
,单独检查:
var actualOptions;
spyOn(modal, 'open').and.callFake(function(options){
actualOptions = options; //capture the actual options
return fakeModal;
});
expect(actualOptions.resolve.employee()).toEqual(employee); //Check the returned employee is actually the one we pass in.
这篇关于单元测试 angular-bootstrap $modal的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!