Angularjs 用承诺模拟服务,以便在另一个服务中进行测试
我有以下服务(为简单起见减少): 我希望测试maxEventTime只有在承诺成功后才设置 我的测试:Angularjs 用承诺模拟服务,以便在另一个服务中进行测试,angularjs,unit-testing,mocking,jasmine,promise,Angularjs,Unit Testing,Mocking,Jasmine,Promise,我有以下服务(为简单起见减少): 我希望测试maxEventTime只有在承诺成功后才设置 我的测试: describe('Service: BasicTimerService', function () { beforeEach(module('myApp')); var mockPromiseService, BasicTimerService, $q, $rootScope, deferred; b
describe('Service: BasicTimerService', function () {
beforeEach(module('myApp'));
var mockPromiseService,
BasicTimerService,
$q,
$rootScope,
deferred;
beforeEach(function(){
mockPromiseService = {
maxEventTime: function() {
return 17000;
}
};
module(function($provide){
$provide.value('PromiseService', mockPromiseService);
});
inject(function(_BasicTimerService_, _$q_, _$rootScope_){
BasicTimerService = _BasicTimerService_;
$rootScope = _$rootScope_;
$q = _$q_;
});
mockPromiseService.get_promise = function() {
var deferred = $q.defer();
deferred.resolve('hello world');
return deferred.promise;
};
});
it('should get maxEventTime once the promise is resolved.', function() {
spyOn(mockPromiseService, 'get_promise').and.callThrough();
spyOn(mockPromiseService, 'maxEventTime').and.callThrough();
$rootScope.$apply();
BasicTimerService.start();
expect(mockPromiseService.get_promise).toHaveBeenCalled();
expect(BasicTimerService.get_isPlaying()).toBe(true);
expect(mockPromiseService.maxEventTime).toHaveBeenCalled();
});
});
我已经确定mockPromiseService.get_promise()已成功调用(第一个expect()已成功),但BasicTimerService中的.then()子句似乎未被调用,我无法找出原因
我尝试了使用$rootScope.$apply()
以及$rootScope.$digest()代码>无效
关于为什么这不起作用,你有什么想法吗?你的start()
方法是异步的,因此如果它工作正常,get\u isplay()
在你检查它的值时将不会是true
。您需要等待结果(修改start()
以返回Benjamin Grunbaum建议的承诺:
it('should get maxEventTime once the promise is resolved.', function(done) {
spyOn(mockPromiseService, 'get_promise').and.callThrough();
spyOn(mockPromiseService, 'maxEventTime').and.callThrough();
$rootScope.$apply();
BasicTimerService.start().then(function () {
expect(mockPromiseService.get_promise).toHaveBeenCalled();
expect(BasicTimerService.get_isPlaying()).toBe(true);
expect(mockPromiseService.maxEventTime).toHaveBeenCalled();
done();
});
});
您也不需要在get\u promise
中使用$q.defer()
(您几乎不需要使用$q.defer()
):
注意:根据$q
文档,您似乎可以使用$rootScope.$apply()
将承诺值传播到它们的然后
处理程序,但我认为您应该将承诺视为承诺并使用然后()
等进行测试。从开始
返回承诺。通常,如果某个执行I/O操作,它应该始终返回该io完成的承诺(或在回调版本中进行回调)。我必须将$rootScope.apply()移到测试的最后一行,但所有其他操作都按照说明进行。感谢您的帮助!
it('should get maxEventTime once the promise is resolved.', function(done) {
spyOn(mockPromiseService, 'get_promise').and.callThrough();
spyOn(mockPromiseService, 'maxEventTime').and.callThrough();
$rootScope.$apply();
BasicTimerService.start().then(function () {
expect(mockPromiseService.get_promise).toHaveBeenCalled();
expect(BasicTimerService.get_isPlaying()).toBe(true);
expect(mockPromiseService.maxEventTime).toHaveBeenCalled();
done();
});
});
mockPromiseService.get_promise = function() {
return $q.when('hello world');
};