【发布时间】:2020-11-20 00:59:23
【问题描述】:
我正在使用新的Redux toolkit。新的 Redux-toolkit 比旧的 redux 高效得多。我使用新的 Redux-toolkit 创建了多个减速器和操作。我稍微解构了 redux-toolkit 设置。我正在使用 Enzyme 和 Jest 进行单元测试。我的 redux 计数器 intialState 是 1。根据我的测试,在 it 范围内,我首先采用 intialState,然后在模拟('click')增加按钮之后,得到了我预期的结果 2。当我尝试在it 范围内测试我的减少按钮时,它会从增加的it 范围中获取结果。如果我将 intialState 1 放在减少按钮的 it 范围内,它会给我失败的测试,因为它预期为 2。我想我需要为此 counter.test 创建 mockStore。由于 redux-toolkit 的语法对我来说是新的,所以我不知道如何在 counter.test 测试套件中创建 mockstore。
附言。还有其他用于获取数据的反应组件,todolist。我也想做unit test 那些组件。如果有人帮我测试这些组件,我会非常高兴。我是单元测试的新手????。
我将代码上传到Codesandbox。
下面我将解释我是如何进行设置并传递给 React 的组件的。
这是计数器减速器
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
"name": `counter`,
"initialState": 1 as number,
"reducers": {
"increment": (state) => state + 1,
"decrement": (state) => state - 1
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
这是 combineReducers
import { combineReducers } from 'redux';
import counter from 'store/reducer/counter';
import todo from 'store/reducer/todo/todo';
import fetchUser from 'store/reducer/fetch';
import fetching from 'store/reducer/createAsyncAxios';
const rootReducer = combineReducers({
counter, //This is my counter Reducer
todo,
fetchUser,
fetching
});
export type IRootState = ReturnType<typeof rootReducer>;
export default rootReducer;
这是我的商店文件
import { configureStore, Action, getDefaultMiddleware } from '@reduxjs/toolkit';
import { ThunkAction } from "redux-thunk";
import rootReducer, { IRootState } from 'store/combineReducer';
const store = configureStore({
"reducer": rootReducer,
"middleware": [...getDefaultMiddleware()]
});
export type AppThunk = ThunkAction<void, IRootState, null, Action<string>>
export default store;
附言。我析构了根文件。首先我创建了一个根文件,我在其中导入了商店,然后我连接到App。我这样做是因为我可以将根文件直接导入测试套件
import React from 'react';
import { Provider } from 'react-redux';
import store from 'store/store';
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
background-color: #282c34;
color: white;
font-family: "Lucida Console", Courier, monospace;
}
`;
interface IProps {
children: JSX.Element[] | JSX.Element;
}
export default ({ children }: IProps) => {
return (
<Provider store={store}>
<GlobalStyle />
{children}
</Provider>
);
};
这就是我的根文件连接到App的方式
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import Root from './root';
ReactDOM.render(
<Root>
<App />
</Root>
,
document.getElementById(`root`)
);
这是我的计数器组件
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from 'store/reducer/counter/index';
import { IRootState } from 'store/combineReducer';
import styled from 'styled-components';
const Button = styled.button`
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
`;
const Text = styled.h1`
color: blue;
`;
export default () => {
const counter = useSelector((state: IRootState) => state.counter);
const dispatch = useDispatch();
return (
<div >
<Text>{counter}</Text>
<Button data-test="increment" onClick={() => dispatch(increment())}>
Increment counter
</Button>
<br></br>
<br></br>
<Button data-test="decrement" onClick={() => dispatch(decrement())}>
Decrement counter
</Button>
</div>
);
};
这是我的counter 测试套件
import React from 'react';
import { mount } from "enzyme"; // mount is full dom renderning function with children
import Counter from 'components/counter';
import Root from "root/index";
let wrapped;
beforeEach(() => {
// I need to create mock store in here. I don't know how to do that.
wrapped = mount(
<Root >
<Counter />
</Root>
);
// console.log(wrapped.debug());
});
afterEach(() => {
wrapped.unmount(); // it cleans the mount after test.
});
describe(`This is counter component`, () => {
it(``, () => {
expect(wrapped.find(`h1`).text()).toEqual(`1`);
});
it(`after click it will increase the value`, () => {
expect(wrapped.find(`h1`).text()).toEqual(`1`);
wrapped.find(`button`).at(0).find(`[data-test="increment"]`).simulate(`click`);
expect(wrapped.find(`h1`).text()).toEqual(`2`);
});
it(`after click it will decrease the value`, () => {
expect(wrapped.find(`h1`).text()).toEqual(`1`); // Test failed: because it Received: "2"
wrapped.find(`button`).at(1).find(`[data-test="decrement"]`).simulate(`click`);
expect(wrapped.find(`h1`).text()).toEqual(`2`); //
});
});
【问题讨论】:
-
redux-mock-store怎么样? -
我可以试试 :)...
-
@k-wasilewski 没有成功。感觉很蠢。
-
我已经添加了一个答案来澄清..
标签: unit-testing jestjs enzyme redux-toolkit react-typescript