我知道这已被多次询问过,我已经查看了其他问题并遵循了这些问题,但我似乎无法解决这个问题。
基本上,我在服务中有一个函数将数据放入pouchDB。函数addTask
将返回一个promise,它将在数据库插入成功时作为结果值解析。
这在浏览器环境中的手动测试期间工作正常,但由于超时而在Jasmine测试期间失败。
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
似乎在规范的then
中作为参数传递的回调永远不会运行。
app = angular.module 'testApp', ['ngMock']
app.service 'Pouch', ($q) ->
db = new PouchDB 'tasks'
return {
addTask : (task) ->
deferred = $q.defer()
db.put task, (task.title + task.due), (err, res) ->
console.log res # Both prints fine
console.log err
deferred.resolve res
return deferred.promise
}
describe 'Service: Pouch', ->
Pouch = {}
$rootScope = {}
beforeEach () ->
module 'testApp'
PouchDB.destroy 'tasks'
inject (_Pouch_, _$rootScope_) ->
Pouch = _Pouch_
$rootScope = _$rootScope_
value = undefined
testTask =
type: 'TASK'
title: 'Feed the kitten'
due: 201120141900
group: ['TODAY', 'TOMORROW']
it 'should add task upon request', (done) ->
promise = Pouch.addTask testTask
promise.then (result) ->
# Never reached here
expect(result.ok).toBe(true)
done()
$rootScope.$apply() # I don't think this is neccessary.
我该怎么办?我也尝试使用$timeout
,但它没有用。
答案 0 :(得分:2)
这看起来是我能想到的两件事之一:
$q.when()
和$timeout.$flush()
进行测试?jasmine. DEFAULT_TIMEOUT_INTERVAL
和beforeEach
将afterEach
设置为更高的数字如果要单独测试,则需要将PouchDB注入依赖项。您无需测试 Pouch ,只需测试您自己的代码:
# Create a service that gets PouchDB from $window
app.service 'PouchDB', ($window) ->
return $window.PouchDB
# Now you can inject it as a dependency!
app.service 'Pouch', ($q, $rootScope, PouchDB) ->
# *now* new it up.
db = new PouchDB 'tasks'
return addTask: (task) ->
deferred = $q.defer()
db.put task, (task.title + task.due), (err, res) ->
$rootScope.$apply -> deferred.resolve res
deferred.promise
您的测试现已被隔离:
describe 'Service: Pouch', ->
Pouch = undefined
$rootScope = undefined
PouchDBMock = undefined
$timeout = undefined
value = undefined
beforeEach () ->
module 'testApp', ($provide) ->
# create your mock
PouchDBMock = jasmine.createSpyObj('PouchDB', ['put', 'get', 'etc']);
# provide it to the container
$provide.value 'PouchDB', PouchDBMock
# No longer necessary, because you're isolated!
# ---> PouchDB.destroy 'tasks' <---
# Now when you inject your Pouch service, it will have
# our PouchDBMock being used inside of it.
# also inject $timeout so you can flush() later
inject (_Pouch_, _$rootScope_, _$timeout_) ->
Pouch = _Pouch_
$rootScope = _$rootScope_
$timeout = _$timeout_
# MOVED: this should be initialized in your beforeEach or your it, not in the body
# of define... that's bad. Every new `it` test could mutate this and it won't reset
# in the beforeEach where you had it.
testTask =
type: 'TASK'
title: 'Feed the kitten'
due: 201120141900
group: ['TODAY', 'TOMORROW']
it 'should add task upon request', (done) ->
# tell the spy on `put` to return something distinct
PouchDBMock.put.andReturn('something special');
# call the method
promise = Pouch.addTask testTask
# handle the promise
promise.then (result) ->
# assert put was called on your mock
expect(PouchDBMock.put).toHaveBeenCalledWith(testTask)
# assert the result was what you expected (the return from the spy)
expect(result).toBe('something special')
# and you're done... even though this wasn't asynchronous
done()
# flush all unresolved promises
$timeout.flush()
答案 1 :(得分:1)
问题是,由于pouchdb回调发生在Angular的摘要周期之外,你必须在pouchdb回调函数中调用$rootScope.$apply()
。
app.service 'Pouch', ($q, $rootScope) -> db = new PouchDB 'tasks'
return {
addTask : (task) ->
deferred = $q.defer()
db.put task, (task.title + task.due), (err, res) ->
deferred.resolve res
$rootScope.$apply()
return deferred.promise
}
答案 2 :(得分:0)
最有可能的问题是PhantomJS,它需要Function.prototype.bind
的垫片才能与PouchDB一起正常工作。你可以从https://github.com/es-shims/es5-shim得到这样的垫片。