此代码中的测试未成功。我似乎无法成功测试异步函数的返回。
describe('mocking services', function () {
var someService, deferred;
beforeEach(function () {
module(function($provide){
$provide.factory('someService', function($q){
return{
trySynch: function(){
return 33;
},
tryAsynch: function(){
deferred = $q.defer();
return deferred.promise;
}
};
});
});
inject(function (_someService_) {
someService = _someService_;
});
});
it('should be able to test values from both functions', function () {
expect(someService.trySynch()).toEqual(33);
var retVal;
someService.tryAsynch().then(function(r){
retVal = r;
});
deferred.resolve(44);
expect(retVal).toEqual(44);
});
});
当我运行它时,我收到以下错误:
Chrome 36.0.1985 (Mac OS X 10.9.4) mocking services should be able to test values from both functions FAILED
Expected undefined to equal 44.
Error: Expected undefined to equal 44.
at null.<anonymous> (/Users/selah/WebstormProjects/macrosim-angular/test/spec/services/usersAndRoles-service-test.js:34:24)
如何让这个测试通过?
答案 0 :(得分:2)
使用$ q模拟异步调用时,由于$ q的实现方式,您需要使用$rootScope.$apply()
。
具体来说,.then
方法不会被同步调用,它被设计为始终是异步的,无论它是如何调用的 - 同步或异步。
为实现这一目标,$ q与$ rootScope集成。因此,在单元测试中,您需要通知$ rootScope更改了某些内容(即 - 触发摘要周期)。为此,请致电$rootScope.$apply()
请参阅here (specifically the "Differences between Kris Kowal's Q and $q section")
工作代码如下所示:
describe('mocking services', function () {
var someService, deferred, rootScope;
beforeEach(function () {
module(function($provide){
$provide.factory('someService', function($q){
return{
trySynch: function(){
return 33;
},
tryAsynch: function(){
deferred = $q.defer();
return deferred.promise;
}
};
});
});
inject(function ($injector) {
someService = $injector.get('someService');
rootScope = $injector.get('$rootScope');
});
});
it('should be able to test values from both functions', function () {
expect(someService.trySynch()).toEqual(33);
var retVal;
someService.tryAsynch().then(function(r){
retVal = r;
});
deferred.resolve(44);
rootScope.$apply();
expect(retVal).toEqual(44);
});
});
答案 1 :(得分:0)
$q
延迟仍然是异步解析。
快速测试,尽管是旧版Angular:http://plnkr.co/edit/yg2COXG0TWBYniXOwJYb
此测试应该有效:
it('should be able to test values from both functions', function (done) {
expect(someService.trySynch()).toEqual(33);
someService.tryAsynch().then(function(r){
expect(r).toEqual(44);
done();
});
deferred.resolve(44);
});
答案 2 :(得分:0)
如果我在测试我的异步函数的expect子句之前运行rootScope.$apply()
,那么测试成功。此外,如果我提供的值不正确,它会失败,正如我所期望的那样。
所以我的测试功能正常,但我不明白为什么rootScope。$ apply()在这里很重要,所以如果有人想复制我的代码并提供解释,我很乐意将你的答案标记为正确解答!
我的工作测试代码如下所示:
describe('mocking services', function () {
var someService, deferred, rootScope;
beforeEach(function () {
module(function($provide){
$provide.factory('someService', function($q){
return{
trySynch: function(){
return 33;
},
tryAsynch: function(){
deferred = $q.defer();
return deferred.promise;
}
};
});
});
inject(function ($injector) {
someService = $injector.get('someService');
rootScope = $injector.get('$rootScope');
});
});
it('should be able to test values from both functions', function () {
expect(someService.trySynch()).toEqual(33);
var retVal;
someService.tryAsynch().then(function(r){
retVal = r;
});
deferred.resolve(44);
rootScope.$apply();
expect(retVal).toEqual(44);
});
});