我有一个需要测试的角度控制器。此控制器调用服务以从服务器检索数据。该服务返回ES6 Promises。
function MyController($scope, MyService) {
$scope.doSomething = function () {
MyService.foo().then() {
whatever...;
};
};
};
在我的Jasmine测试中,我模拟了返回Promises的服务:
var resolve;
var reject;
createPromise = function () {
return new Promise(function (_resolve, _reject) {
resolve = _resolve;
reject = _reject;
});
};
var myServiceMock = {
doSomething: jasmine.createSpy('doSomething').and.callFake(createPromise)
};
beforeEach(module('someApp', function ($provide) {
$provide.value('MyService', myServiceMock);
}));
我使用或不使用参数手动调用全局解析(或拒绝)来检查我的控制器。
it('shall call the service', function () {
$scope = $rootScope.$new();
controller = $controller('MyService', { $scope: $scope });
controller.doSomething();
myService.resolve();
expect(whatever...);
});
问题是解析调用是异步的。所以当我正在运行then函数时,我正在测试我的预期结果。
我没有返回Promises,而是尝试返回简单的自定义对象,它会将解析转换为同步调用,但事实证明Promises有一些特定的规则,这些规则在模拟中重新实现会非常麻烦(就像你当时那样。) ).catch()。然后模式,例如)。
有没有办法在Jasmine中以简单和同步的方式测试这种东西?
答案 0 :(得分:2)
你需要告诉Jasmine你的测试是异步的,它应该等到它完成才能确定它是否失败。您可以在规范声明(done
调用)中添加it
参数,并在期望结束时调用done
来执行此操作:
it('shall call the service', function (done) {
$scope = $rootScope.$new();
controller = $controller('MyService', { $scope: $scope });
var promise =
controller.doSomething()
.then(function() {
expect(whatever...);
done();
});
myService.resolve();
});
让您的模拟自动解决的更简单方法是使用Promise.resolve
方法:
doSomething: jasmine.createSpy('doSomething').and.returnValue(Promise.resolve())
然后您不需要致电myService.resolve
- 模拟会自动返回已解决的承诺。
我最近开始使用jasmine-promises模块,这使得编写promise函数变得更加容易 - 并确保如果promise拒绝,则会报告错误和调用堆栈,以便于调试。使用jasmine-promises
,这将成为:
it('shall call the service', function () {
$scope = $rootScope.$new();
controller = $controller('MyService', { $scope: $scope });
return controller.doSomething()
.then(function() {
expect(whatever...);
});
});