使用测试库测试Redux更改

n8ghc7c1  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(174)

我在测试我的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场景。

c6ubokkw

c6ubokkw1#

redux-mock-store的文档中有一条注解
请注意,这个库被设计来测试与操作相关的逻辑,而不是与reducer相关的逻辑。换句话说,它不更新Redux存储。
看一下dispatch()方法,它只是将redux操作存储在actions数组中。它不执行任何reducer。它甚至在设置过程中不接受任何reducer。它只通知订阅者列表。因此状态将始终相同。
要测试reducer和它的状态,你不需要任何类型的mock,只需要使用redux中的createStore,这样状态就会被更新,useSelector()钩子就会被再次执行。

e5njpo68

e5njpo682#

我真傻
看起来我使用了redux-mock-store,这就是问题所在
通过像这样使用mockstore,我没有得到任何“reducer”操作。

const mockStore = configureStore();

let store = mockStore(getData());

如果我在测试的“before”方法中创建了应用程序中使用的ACTUAL存储,那么我的测试就可以工作了,因为它们也可以获得归约器:

const store = createStore(
    combineReducers({
        // login: login,
        products: products,
        order: order,
        admin: admin
    }), getData()
);
return store;

一般mock-store shouldnt be used

相关问题