我在测试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"。然而,当我在console.info中查看HTML时;选择";但是不存在被设置为被选择的选项(即<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处正确中断。但它并没有在减速器级别上断裂。
在它达到减速器级别之前,在我的测试中,它在以下位置断裂:
comboboxes = await screen.findAllByRole("combobox");
这基本上意味着反应行为在到达测试线之前还没有完成。
我"等"对了吗?
后台是否发生了我不知道的异步事件?这一切都应该是"同步"的,因为就我而言,这是一个微不足道的冗余场景。
redux模拟商店的文档中有一条注释
请注意,此库旨在测试与操作相关的逻辑,而不是与减速器相关的逻辑。换句话说,它不会更新Redux商店。
看看dispatch((方法,它只是将redux操作存储在actions
数组中。它不执行任何减速器。它甚至在设置过程中不接受任何一个。它只通知订阅者列表。因此,这个州将永远是一样的。
要测试reducer及其状态,您不需要任何类型的mock,只需使用redux
中的createStore
即可。从而状态将被更新并且useSelector()
钩子将被再次执行。
愚蠢的我,
似乎我在使用redux模拟存储,这就是的问题
通过使用这样的mockstore,我得到了no"减速器";行动正在发生。
const mockStore = configureStore();
let store = mockStore(getData());
如果我在";在";我的测试方法,然后我的测试工作,因为他们也得到了减速器:
const store = createStore(
combineReducers({
// login: login,
products: products,
order: order,
admin: admin
}), getData()
);
return store;
一般情况下,模拟商店不应使用