我有这样的reducer,使用fetch
API作为它的基础最终:
export const fetchRelatedFamilies = () => {
return (dispatch, getState) => {
if (isEmpty(getState().relatedFamiliesById)) {
dispatch({ type: REQUEST_RELATED_FAMILIES_BY_ID })
new HttpRequestHelper('/api/related_families',
(responseJson) => {
dispatch({ type: RECEIVE_RELATED_FAMILIES_BY_ID, updates: responseJson.relatedFamiliesById })
},
e => dispatch({ type: RECEIVE_RELATED_FAMILIES_BY_ID, error: e.message, updates: {} }),
).get()
}
}
}
HttpRequestHelper的程式码如下:https://github.com/broadinstitute/seqr/blob/master/ui/shared/utils/httpRequestHelper.js
下面是我如何尝试测试它(但它不工作):
import configureStore from 'redux-mock-store'
import fetchMock from 'fetch-mock'
import thunk from 'redux-thunk'
import { cloneDeep } from 'lodash'
import { fetchRelatedFamilies, REQUEST_RELATED_FAMILIES_BY_ID, RECEIVE_RELATED_FAMILIES_BY_ID } from 'redux/rootReducer'
import { STATE1 } from '/shared/components/panel/fixtures.js'
describe('fetchRelatedFamilies', () => {
const middlewares = [thunk]
const testActionsDispatch = async (currstate, expectedActions) => {
const store = configureStore(middlewares)(currstate)
store.dispatch(fetchRelatedFamilies())
// need to mimick wait for async actions to be dispatched
//await new Promise((r) => setTimeout(r, 200));
expect(store.getActions()).toEqual(expectedActions)
}
afterEach(() => {
fetchMock.reset()
fetchMock.restore()
})
it('Dispatches correct actions when data - relatedFamiliesById - is absent in state', () => {
const relatedFamiliesById = cloneDeep(STATE1.relatedFamiliesById)
fetchMock
.getOnce('/api/related_families', { body: relatedFamiliesById, headers: { 'content-type': 'application/json' } })
STATE1.relatedFamiliesById = {}
const expectedActions = [
{ type: REQUEST_RELATED_FAMILIES_BY_ID },
{ type: RECEIVE_RELATED_FAMILIES_BY_ID, updates: relatedFamiliesById }
]
testActionsDispatch(STATE1, expectedActions)
})
})
我在结果存储操作中没有看到{ type: RECEIVE_RELATED_FAMILIES_BY_ID, updates: relatedFamiliesById }
,所以我尝试使用以下技巧:await new Promise((r) => setTimeout(r, 200));
,希望这是异步fetch
的问题,但它导致的是,无论预期的操作是什么,测试都会通过,就好像await
后面的代码被完全忽略了一样。我不能使用store.dispatch(fetchRelatedFamilies()).then(...
,可能是因为没有返回Promise
,并且我得到了then access of undefined
错误。我尝试从库中使用waitFor
:https://testing-library.com/docs/guide-disappearance/,但是由于项目本身的性质和版本,我在安装库本身时遇到了很大的麻烦,所以我仍然需要以某种方式避免它。
因此,我唯一的问题是如何使异步reducer内部的操作出现,在本例中为{ type: RECEIVE_RELATED_FAMILIES_BY_ID, updates: relatedFamiliesById }
。
1条答案
按热度按时间q35jwt9p1#
当前代码的问题是,尽管您在
testActionsDispatch
帮助器方法中等待了200ms(以便解决模拟的承诺),但您在测试代码中并没有等待解决该200ms的承诺。为了做到这一点,你必须声明你的测试是异步的,并等待
testActionsDispatch
代码的执行:现在应该可以了,但是我们在使用这个
testActionsDispatch
助手的每个测试中增加了200ms的延迟。这可能会在启动测试时增加很多时间,最终在逻辑层面上并不能真正确保承诺得到解决。一个更好的方法是在reducer中返回promise,这样我们就可以等待它在测试中直接解析(我假设
HttpRequestHelper
中的get
方法返回通过fetch创建的promise并返回它):然后,在你的助手中,你可以简单地等待这个返回的承诺来解决: