我在测试我的redux应用程序时遇到了困难。我不确定是否存在某种异步问题,或者我对React测试库不太了解。不用说,我对RTL很困惑。使用Enzyme时,我对这类东西没有任何问题。
我想测试一个基本上是“产品”的组件,它有一些文本和一个“数量”组合框。
该组件非常简单,如下所示:
function ItemBox(props: Props) {
const dispatch = useDispatch();
let selected = ""
if (props.product.amount && props.product.amount > 0) {
selected = "selected"
}
function handleChangeQuantity(e: any) {
dispatch(createUpdateProductSelection({value: e.currentTarget.value, productid: props.product.id}));
}
return(
<div className={"item-box " + selected}>
<div className={"item-box-desc " + selected} title={props.product.name} >
{props.product.name}
</div>
<div className={"item-box-bottom"} >
<select className={"item-box-options"} id="qty" onChange={handleChangeQuantity} value={props.product.amount}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
</div>
)
}
在我的减速机我捕捉行动和更新的产品。
export function productsReducer(state: ProductsState, action: AnyAction): ProductsState {
if (createUpdateProductSelection.match(action)) {
let allProducts = state.allProducts.map((item): Product => {
if (item.id === action.payload.productid) {
return {
...item,
amount: action.payload.value
}
}
return item;
})
return {
...state,
allProducts: allProducts,
};
}
return state;
}
在实际应用中,这一切都工作正常。
当我开始写测试的时候,事情变得很奇怪。我的测试看起来像这样:
let comboboxes: HTMLInputElement[] = await screen.findAllByRole("combobox");
fireEvent.change(comboboxes[0], {target: {value: "3"}})
comboboxes = await screen.findAllByRole("combobox");
expect(comboboxes[0].value).toEqual("3")
console.info("" + screen.debug(comboboxes[0]))
测试通过了,因为它发现组合框已设置为“3”。但是,当我查看www.example.com中的HTML时console.info,我看到了“select”,但没有设置为“selected”的选项(即<option value="3" selected>
)。
它看起来像这样:
<select class="item-box-options" id="qty">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
也许这是一个问题,该组件是一个受控组件?
在任何情况下,通过测试进行的调试都显示它在回调handleChangeQuantity处正确中断。但它在reducer级别没有中断。
在到达减速器水平之前,在我的测试中,它在这条线处断裂:
comboboxes = await screen.findAllByRole("combobox");
这基本上意味着React行为在到达此测试行之前尚未完成。
我的“等待”正确吗?
是不是后台发生了一些我不知道的异步的事情?这应该都是“同步”的,因为就我而言,这是一个微不足道的redux场景。
2条答案
按热度按时间c6ubokkw1#
在redux-mock-store的文档中有一条注解
请注意,这个库被设计来测试与操作相关的逻辑,而不是与reducer相关的逻辑。换句话说,它不更新Redux存储。
看一下dispatch()方法,它只是将redux操作存储在
actions
数组中。它不执行任何reducer。它甚至在设置过程中不接受任何reducer。它只通知订阅者列表。因此状态将始终相同。要测试reducer和它的状态,你不需要任何类型的mock,只需要使用
redux
中的createStore
,这样状态就会被更新,useSelector()
钩子就会被再次执行。e5njpo682#
我真傻
看起来我使用了redux-mock-store,这就是问题所在
通过像这样使用mockstore,我没有得到任何“reducer”操作。
如果我在测试的“before”方法中创建了应用程序中使用的ACTUAL存储,那么我的测试就可以工作了,因为它们也可以获得归约器:
一般mock-store shouldnt be used