英文:
How to test thunk with redux-toolkit slice?
问题
这是您的代码片段的翻译:
我有一个简单的THUNK:
import { AppDispatch } from "../store";
import { Api } from "../../shared/api/index";
import { registrationFormSlice } from "../registration";
export const logIn =
(email: string, password: string) =>
async (dispatch: AppDispatch) => {
try {
const { status } = await Api.auth.logIn({ email, password });
if (status === 200) {
dispatch(registrationFormSlice.actions.reset());
}
} catch (error: any) {
console.error(error);
}
};
请问还有其他需要翻译的内容吗?
英文:
I have a simple THUNK:
import { AppDispatch } from "../store";
import { Api } from "../../shared/api/index";
import { registrationFormSlice } from "../registration";
export const logIn =
(email: string, password: string) =>
async (dispatch: AppDispatch) => {
try {
const { status } = await Api.auth.logIn({ email, password });
if (status === 200) {
dispatch(registrationFormSlice.actions.reset());
}
} catch (error: any) {
console.error(error);
}
};
How can I test it?
I tried to find the answer on my own, but everything I could find did not give an answer or was very difficult to understand. I can't even write how I'm testing this THUNK as I can't figure out where to start.
答案1
得分: 0
如果你只想测试与操作相关的逻辑,可以使用 redux-mock-store 包。
> 用于测试 Redux 异步 action creators 和 middleware 的模拟 store。模拟 store 会创建一个包含已分发的 actions 的数组,用作测试的 action 记录。
> 请注意,该库旨在测试与 action 相关的逻辑,而不是 reducer 相关的逻辑。
例如:
api.ts
:
const Api = {
auth: {
async logIn(payload) {
return fetch('http://localhost:3000/api/login')
}
}
}
export { Api }
registration.ts
:
import { createSlice } from '@reduxjs/toolkit';
const registrationFormSlice = createSlice({
name: 'registration',
initialState: {},
reducers: {
reset() { }
}
})
export { registrationFormSlice }
thunk.ts
:
import { Api } from "./api";
import { registrationFormSlice } from "./registration";
type AppDispatch = any;
export const logIn =
(email: string, password: string) =>
async (dispatch: AppDispatch) => {
try {
const { status } = await Api.auth.logIn({ email, password });
if (status === 200) {
dispatch(registrationFormSlice.actions.reset());
}
} catch (error: any) {
console.error(error);
}
};
thunk.test.ts
:
import { AnyAction } from 'redux';
import configureStore, { MockStoreCreator } from 'redux-mock-store'
import thunk, { ThunkDispatch } from 'redux-thunk'
import { logIn } from './thunk';
import { Api } from "./api";
import { registrationFormSlice } from './registration';
type RootState = any;
const middlewares = [thunk]
type DispatchExts = ThunkDispatch<RootState, undefined, AnyAction>
const mockStoreCreator: MockStoreCreator<RootState, DispatchExts> =
configureStore<RootState, DispatchExts>(middlewares)
describe('thunk', () => {
afterEach(() => {
jest.restoreAllMocks();
})
test('should pass', () => {
jest.spyOn(Api.auth, 'logIn').mockResolvedValue({ status: 200 } as unknown as Response)
const store = mockStoreCreator();
return store.dispatch(logIn('example@gmail.com', '123')).then(() => {
const actions = store.getActions();
expect(actions).toEqual([registrationFormSlice.actions.reset()])
})
})
})
测试结果:
PASS stackoverflow/76302702/thunk.test.ts (19.876 s)
thunk
✓ should pass (7 ms)
-----------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------------|---------|----------|---------|---------|-------------------
All files | 88.24 | 50 | 60 | 87.5 |
api.ts | 66.67 | 100 | 0 | 66.67 | 4
registration.ts | 100 | 100 | 0 | 100 |
thunk.ts | 90.91 | 50 | 100 | 90 | 15
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 21.879 s
英文:
If you only want to test the action-related logic, you can use redux-mock-store package.
> A mock store for testing Redux async action creators and middleware. The mock store will create an array of dispatched actions which serve as an action log for tests.
> Please note that this library is designed to test the action-related logic, not the reducer-related one.
E.g.
api.ts
:
const Api = {
auth: {
async logIn(payload) {
return fetch('http://localhost:3000/api/login')
}
}
}
export { Api }
registration.ts
:
import { createSlice } from '@reduxjs/toolkit';
const registrationFormSlice = createSlice({
name: 'registration',
initialState: {},
reducers: {
reset() { }
}
})
export { registrationFormSlice }
thunk.ts
:
import { Api } from "./api";
import { registrationFormSlice } from "./registration";
type AppDispatch = any;
export const logIn =
(email: string, password: string) =>
async (dispatch: AppDispatch) => {
try {
const { status } = await Api.auth.logIn({ email, password });
if (status === 200) {
dispatch(registrationFormSlice.actions.reset());
}
} catch (error: any) {
console.error(error);
}
};
thunk.test.ts
:
import { AnyAction } from 'redux';
import configureStore, { MockStoreCreator } from 'redux-mock-store'
import thunk, { ThunkDispatch } from 'redux-thunk'
import { logIn } from './thunk';
import { Api } from "./api";
import { registrationFormSlice } from './registration';
type RootState = any;
const middlewares = [thunk]
type DispatchExts = ThunkDispatch<RootState, undefined, AnyAction>
const mockStoreCreator: MockStoreCreator<RootState, DispatchExts> =
configureStore<RootState, DispatchExts>(middlewares)
describe('thunk', () => {
afterEach(() => {
jest.restoreAllMocks();
})
test('should pass', () => {
jest.spyOn(Api.auth, 'logIn').mockResolvedValue({ status: 200 } as unknown as Response)
const store = mockStoreCreator();
return store.dispatch(logIn('example@gmail.com', '123')).then(() => {
const actions = store.getActions();
expect(actions).toEqual([registrationFormSlice.actions.reset()])
})
})
})
Test result:
PASS stackoverflow/76302702/thunk.test.ts (19.876 s)
thunk
✓ should pass (7 ms)
-----------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------------|---------|----------|---------|---------|-------------------
All files | 88.24 | 50 | 60 | 87.5 |
api.ts | 66.67 | 100 | 0 | 66.67 | 4
registration.ts | 100 | 100 | 0 | 100 |
thunk.ts | 90.91 | 50 | 100 | 90 | 15
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 21.879 s
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论