Ответ 1
Чтобы высмеять функцию, которая возвращает обещание, она также должна вернуть обещание, которое затем должно быть разрешено как отдельный шаг.
В вашем случае deferred.resolve()
, который вы передаете шпиону, нужно заменить на deferred.promise
, а отложенное .resolve() выполняется отдельно.
beforeEach(function() {
var deferred = $q.defer();
spyOn(dialogFactory, "confirmDeleteDialog").and.returnValue(deferred.promise);
spyOn(requestNotificationChannel, "deleteMessage");
$scope.deleteMessage(5);
deferred.resolve();
$rootScope.$digest();
});
it("delete message notification is called", function() {
expect(requestNotificationChannel.deleteMessage).toHaveBeenCalled();
});
Я подозреваю, что вам также нужно вызвать $rootScope.$digest()
, поскольку реализация Angular обещания привязана к циклу дайджеста.
Кроме того, немного не связанный с вашим вопросом, но я не думаю, что вам нужно создать свой собственный отложенный объект в confirmDeleteDialog
. Образец (анти), который вы используете, был помечен как "Забытое обещание", как в http://taoofcode.net/promise-anti-patterns/
Когда проще, использует меньше кода, и я думаю, что это позволяет улучшить обработку ошибок, вы можете просто вернуть обещание, которое создает служба $modal
:
var modalInstance = $modal.open({...});
return modalInstance.result;
Если вы хотите изменить то, что видит вызывающая функция, с точки зрения разрешенных/отклоненных значений, вы можете создать цепочное обещание, возвращая результат then
:
var modalInstance = $modal.open({...});
return modalInstance.result.then(function(successResult) {
return 'My other success result';
}, function(failureReason) {
return $q.reject('My other failure reason');
});
Обычно вы хотите сделать это, если не хотите выставлять внутреннюю работу функции своему вызывающему. Это аналогично концепции повторного выброса исключения в синхронное программирование.