环境:
这是我的控制器,它的目的是从$ stateParams获取一个值,然后使用它来执行DELETE请求。 现在它应该询问用户,删除对象。 这是通过sweetalert完成的。
我删除了ngdoc注释和任意SWAL配置。
ClientDeleteController.js:
angular.module('app.data').controller('ClientDeleteController', [
'$stateParams', '$q',
function ($stateParams, $q) {
'use strict';
var vm = this;
vm.clientId = $stateParams.id;
vm.promptDeferred = null;
vm.prompt = function () {
// create promise
var d = $q.defer();
vm.promptDeferred = d;
// create prompt
swal({ .... }, vm.swalCallback);
};
vm.swalCallback = function (confirmed) {
if (confirmed) {
console.info('resolving...');
vm.promptDeferred.resolve();
} else {
console.info('rejecting...');
vm.promptDeferred.reject();
}
};
vm.delete = function () {
vm.prompt();
vm.promptDeferred.promise.then(vm.performDelete);
};
vm.performDelete = function () {
console.info('performing');
};
}]);
这是测试套件:
ClientDeletecontrollerSpec.js
describe('Controller:ClientDeleteController', function () {
var controller
, $httpBackend
, $rootScope
, $controller
, scope
, $q
, $stateParams = {id: 1}
, resolvePromise = true
;
swal = function (options, callback) {
console.info('i am swal, this is callback', callback+'', resolvePromise);
callback(resolvePromise);
};
beforeEach(function () {
module('app');
module('app.data');
module('ui.bootstrap');
module(function ($provide) {
$provide.service('$stateParams', function () {
return $stateParams;
});
});
inject(function (_$controller_, _$rootScope_, _$q_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
$q = _$q_;
scope = $rootScope.$new();
controller = $controller('ClientDeleteController', {$scope: scope, $q: $q});
});
});
describe('basic controller features', function () {
it('should be defined', function () {
expect(controller).toBeDefined();
});
it('should get the client id from the state params', function () {
expect(controller.clientId).toBeDefined();
expect(controller.clientId).toEqual($stateParams.id);
});
});
fdescribe('client delete process', function () {
it('should ask the user if he really wants to delete the client', function () {
spyOn(controller, 'prompt').and.callThrough();
controller.delete();
expect(controller.prompt).toHaveBeenCalled();
});
it('should create a promise', function () {
controller.prompt();
expect(controller.promptDeferred).toBeDefined();
});
it('should delete when the user clicked yes', function () {
spyOn(controller, 'performDelete').and.callThrough();
controller.delete();
expect(controller.performDelete).toHaveBeenCalled();
});
it('should not delete when the user clicked no', function () {
spyOn(controller, 'performDelete').and.callThrough();
resolvePromise = false;
controller.delete();
expect(controller.performDelete).not.toHaveBeenCalled();
});
});
});
测试should delete when the user clicked yes
失败,测试should not delete when the user clicked no
返回误报。
swal mock中的console.info(...)
会记录正确的回调函数。函数本身的日志也被记录,告诉我,回调被触发。
因为在下一行中,我调用了vm.promptDeferred.resolve()
resp。 .reject()
,我希望这个电话确实发生了。
尽管如此,测试结果为Expected spy performDelete to have been called.
。
我以同样的方式在另一个测试中嘲笑了swal并且它工作正常。 我不明白为什么承诺不会得到解决。
注意:当我没有直接将承诺存储在控制器上但从prompt()
返回并使用常规.prompt().then(...)
时,它也无法正常工作。
日志是一样的,我喜欢尽可能地分割函数,因此更容易理解,更容易测试和记录。
在这个应用程序中有数百个其他测试,但我不明白,为什么这个测试不能按预期工作。
感谢您的任何见解。
答案 0 :(得分:1)
如果在测试中调用delete之后执行$ rootScope。$ digest()会发生什么?
根据我的经验,在测试期间(或者rootScope。$ apply()或$ httpBackend.flush())有必要做出类似角度解析的承诺。