问题
So i tried to get the promises to work in my angular app tests, can anyone figure out what im doing wrong here it keeps returning:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
I don't know if it's $q.
FYI i also tried the it('test', function(done){... done();})
Controller
(function() {
'use strict';
angular
.module('controller.editor', [])
.controller('EditorController', EditorController);
function EditorController($scope, $q) {
var vm = this;
angular.extend(vm, {
hack: hack
});
function hack(bool) {
return $q(function(resolve, reject) {
if (bool) {
resolve(true);
}
reject(false);
});
}
}
});
Test
describe('EditorController', function() {
var vm, scope, $controller, $rootScope, $injector;
beforeEach(function() {
module('app');
//Inject
inject(function(_$injector_) {
$injector = _$injector_;
$controller = $injector.get('$controller');
$rootScope = $injector.get('$rootScope');
// Create new scope object
scope = $rootScope.$new();
// Bind the controller
vm = $controller('EditorController', {
$scope: scope
});
});
});
describe('#addCustom', function() {
it('test', function(done) {
var aHack = vm.hack(true);
aHack.then(function(bool){
// Resolve
expect(bool).to.be.eq(true);
done();
}, function() {
// Reject
expect(bool).to.be.eq(false);
done();
});
});
});
});
回答1:
When testing promises in angular, it's a best practice to depend on angular machinery to do its job to resolve promises synchronously instead of asynchronously.
This makes the code easier to read and maintain.
It's also less error prone; doing assertions in .then()
is an anti-pattern because if the callback is never called, your assertions will never run.
To use the angular way of testing, you should:
- remove
done
- do
$rootScope.$digest()
in the test to resolve promises - do your assertions
Applying this to your code would be:
describe('#addCustom', function() {
it('test', function() {
var __bool = false;
var aHack = vm.hack(true).then(function(bool) {
__bool = bool;
});
$rootScope.$digest();
expect(__bool).to.be.eq(true);
});
});
But it's tricky, because $rootScope.$digest
resolves only $q
promises, not all promises, particularly not the promises created via Promise()
constructor from various es5 shims, see this:
Promise resolved too late in angularjs jasmine test
See also:
http://brianmcd.com/2014/03/27/a-tip-for-angular-unit-tests-with-promises.html
回答2:
The problem is that your Promise is resolved before you setup your 'then' behavior.
Take a look at these examples that all use a setTimeout.
来源:https://stackoverflow.com/questions/35180958/promises-with-q-and-angular-in-karma-mocha-chai