This is a somewhat of a follow-on question to this one: Mocking $modal in AngularJS unit tests
The referenced SO is an excellent question with very useful answer. Th
Alternatively, if you're using jasmine, you can mock the $uibModalInstance
using the createSpy
method:
beforeEach(inject(function ($controller, $rootScope) {
$scope = $rootScope.$new();
$uibModalInstance = jasmine.createSpyObj('$uibModalInstance', ['close', 'dismiss']);
ModalCtrl = $controller('ModalCtrl', {
$scope: $scope,
$uibModalInstance: $uibModalInstance,
});
}));
And test it without having to call spyOn
on each method, let's say you have 2 scope methods, cancel()
and confirm()
:
it('should let the user dismiss the modal', function () {
expect($scope.cancel).toBeDefined();
$scope.cancel();
expect($uibModalInstance.dismiss).toHaveBeenCalled();
});
it('should let the user confirm the modal', function () {
expect($scope.confirm).toBeDefined();
$scope.confirm();
expect($uibModalInstance.close).toHaveBeenCalled();
});
Follow below given steps:
Define stub for ModalInstance like give below
uibModalInstanceStub = {
close: sinon.stub(),
dismiss: sinon.stub()
};
Pass the modal instance stub while creating controller
function createController() {
return $controller(
ppcConfirmGapModalComponentFullName,
{
$scope: scopeStub,
$uibModalInstance: uibModalInstanceStub
});
}
});
Stub methods close(), dismiss() will get called as part of the tests
it('confirm modal - verify confirm action, on ok() call calls modalInstance close() function', function() { action = 'Ok'; scopeStub.item = testItem; createController(); scopeStub.ok(); });
The same problem is with $uidModalInstance and you can solve it in similar way:
var uidModalInstance = { close: function() {}, dismiss: function() {} };
$ctrl = $controller('ModalInstanceCtrl', {
$scope: $scope,
$uibModalInstance: uidModalInstance
});
or as said @yvesmancera you can use jasmine.createSpy method instead, like:
var uidModalInstance = jasmine.createSpyObj('$uibModalInstance', ['close', 'dismiss']);
$ctrl = $controller('ModalInstanceCtrl', {
$scope: $scope,
$uibModalInstance: uidModalInstance
});
I test the controllers used in modal dialogs by instantiating the controller directly (the same way you initially thought to do it above).
Since there there's no mocked version of $modalInstance
, I simply create a mock object and pass that into the controller.
var modalInstance = { close: function() {}, dismiss: function() {} };
var items = []; // whatever...
beforeEach(inject(function($rootScope) {
scope = $rootScope.$new();
ctrl = $controller('ModalInstanceCtrl', {
$scope: scope,
$modalInstance: modalInstance,
items: items
});
}));
Now the dependencies for the controller are satisfied and you can test this controller like any other controller.
For example, I can do spyOn(modalInstance, 'close')
and then assert that my controller is closing the dialog at the appropriate time.