如何使用玩笑在 redux saga 中测试嵌套的 firestore 批处理函数?
How to test nested firestore batch functions in redux saga using jest?
在一个反应项目中,我有一个 redux-saga 文件,我在 firebase 后端 (firestore) 上创建并保存新项目。
在那个 saga 函数中,我首先获取一个新的写入批处理对象,然后更新 firestore 文档,最后提交批处理。
佐贺工人
import { call, put } from 'redux-saga/effects'
import { db } from './firebase' // db: firebase.firestore()
export function* mySaga(item) {
try {
// init firestore batch.
const batch = yield call(db, db.batch)
// Set firestore document and save new item.
const itemRef = yield call ([db, db.doc], `/items/${item.id}`)
yield call([batch, batch.set], itemRef , item)
// Commit the batch.
yield call([batch, batch.commit])
yield put({type: 'success'})
} catch (err) {
yield put({type: 'error', payload: err})
}
}
佐贺工人的考验
import * as sagas from './mySaga'
describe('mySaga', () => {
const spyOnDoc = jest.spyOn(db, 'doc')
it('handles item creation', async () => {
const dispatched = []
await runSaga(
{ dispatch: action => dispatched.push(action) },
sagas.mySaga,
).toPromise()
expect(spyOnDoc).toHaveBeenCalledTimes(1)
// !!! Here I need to check for nested set and commit functions of the batch object created in saga.
})
})
我如何测试批处理函数的嵌套 "set" 和 "commit" 函数以检查它们是否被调用 x 次并使用正确的输入调用?
如有任何帮助,我们将不胜感激。
After several attemps I figured out a way to accomplishing this kind of tests. In case if someone needs this solution, here it is.
db.batch()
方法创建一个 firebase.firestore.WriteBatch
对象。而这个对象有commit
、set
、update
和delete
方法。可以找到更多详细信息 here.
最终 Saga 工人测试
import * as sagas from './mySaga'
import { db } from './firebase' // db: firebase.firestore()
describe('mySaga', () => {
const spyOnDoc = jest.spyOn(db, 'doc')
// We are mocking the methods of this predefined object.
firestore.WriteBatch.set = jest.fn()
firestore.WriteBatch.commit = jest.fn()
// Then we implement those created mocks into the batch's mock implementation.
const spyOnBatch = jest.spyOn(db, 'batch').mockImplementation(() => ({
set: firestore.WriteBatch.set,
commit: firestore.WriteBatch.commit,
}))
it('handles item creation', async () => {
const dispatched = []
await runSaga(
{ dispatch: action => dispatched.push(action) },
sagas.mySaga,
{id: 123} // Item
).toPromise()
expect(spyOnDoc).toHaveBeenCalledTimes(1)
// Finally, we can test those nested object functions as below.
expect(firestore.WriteBatch.commit).toHaveBeenCalledTimes(1)
expect(firestore.WriteBatch.set).toHaveBeenCalledTimes(1)
expect(firestore.WriteBatch.set).toHaveBeenCalledWith(db.doc('/items/123'), {id: 123})
})
})
在一个反应项目中,我有一个 redux-saga 文件,我在 firebase 后端 (firestore) 上创建并保存新项目。
在那个 saga 函数中,我首先获取一个新的写入批处理对象,然后更新 firestore 文档,最后提交批处理。
佐贺工人
import { call, put } from 'redux-saga/effects'
import { db } from './firebase' // db: firebase.firestore()
export function* mySaga(item) {
try {
// init firestore batch.
const batch = yield call(db, db.batch)
// Set firestore document and save new item.
const itemRef = yield call ([db, db.doc], `/items/${item.id}`)
yield call([batch, batch.set], itemRef , item)
// Commit the batch.
yield call([batch, batch.commit])
yield put({type: 'success'})
} catch (err) {
yield put({type: 'error', payload: err})
}
}
佐贺工人的考验
import * as sagas from './mySaga'
describe('mySaga', () => {
const spyOnDoc = jest.spyOn(db, 'doc')
it('handles item creation', async () => {
const dispatched = []
await runSaga(
{ dispatch: action => dispatched.push(action) },
sagas.mySaga,
).toPromise()
expect(spyOnDoc).toHaveBeenCalledTimes(1)
// !!! Here I need to check for nested set and commit functions of the batch object created in saga.
})
})
我如何测试批处理函数的嵌套 "set" 和 "commit" 函数以检查它们是否被调用 x 次并使用正确的输入调用?
如有任何帮助,我们将不胜感激。
After several attemps I figured out a way to accomplishing this kind of tests. In case if someone needs this solution, here it is.
db.batch()
方法创建一个 firebase.firestore.WriteBatch
对象。而这个对象有commit
、set
、update
和delete
方法。可以找到更多详细信息 here.
最终 Saga 工人测试
import * as sagas from './mySaga'
import { db } from './firebase' // db: firebase.firestore()
describe('mySaga', () => {
const spyOnDoc = jest.spyOn(db, 'doc')
// We are mocking the methods of this predefined object.
firestore.WriteBatch.set = jest.fn()
firestore.WriteBatch.commit = jest.fn()
// Then we implement those created mocks into the batch's mock implementation.
const spyOnBatch = jest.spyOn(db, 'batch').mockImplementation(() => ({
set: firestore.WriteBatch.set,
commit: firestore.WriteBatch.commit,
}))
it('handles item creation', async () => {
const dispatched = []
await runSaga(
{ dispatch: action => dispatched.push(action) },
sagas.mySaga,
{id: 123} // Item
).toPromise()
expect(spyOnDoc).toHaveBeenCalledTimes(1)
// Finally, we can test those nested object functions as below.
expect(firestore.WriteBatch.commit).toHaveBeenCalledTimes(1)
expect(firestore.WriteBatch.set).toHaveBeenCalledTimes(1)
expect(firestore.WriteBatch.set).toHaveBeenCalledWith(db.doc('/items/123'), {id: 123})
})
})