如何使用redux-toolkit的slice来测试thunk?

huangapple go评论97阅读模式
英文:

How to test thunk with redux-toolkit slice?

问题

这是您的代码片段的翻译:

  1. 我有一个简单的THUNK
  2. import { AppDispatch } from "../store";
  3. import { Api } from "../../shared/api/index";
  4. import { registrationFormSlice } from "../registration";
  5. export const logIn =
  6. (email: string, password: string) =>
  7. async (dispatch: AppDispatch) => {
  8. try {
  9. const { status } = await Api.auth.logIn({ email, password });
  10. if (status === 200) {
  11. dispatch(registrationFormSlice.actions.reset());
  12. }
  13. } catch (error: any) {
  14. console.error(error);
  15. }
  16. };

请问还有其他需要翻译的内容吗?

英文:

I have a simple THUNK:

  1. import { AppDispatch } from "../store";
  2. import { Api } from "../../shared/api/index";
  3. import { registrationFormSlice } from "../registration";
  4. export const logIn =
  5. (email: string, password: string) =>
  6. async (dispatch: AppDispatch) => {
  7. try {
  8. const { status } = await Api.auth.logIn({ email, password });
  9. if (status === 200) {
  10. dispatch(registrationFormSlice.actions.reset());
  11. }
  12. } catch (error: any) {
  13. console.error(error);
  14. }
  15. };

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:

  1. const Api = {
  2. auth: {
  3. async logIn(payload) {
  4. return fetch('http://localhost:3000/api/login')
  5. }
  6. }
  7. }
  8. export { Api }

registration.ts:

  1. import { createSlice } from '@reduxjs/toolkit';
  2. const registrationFormSlice = createSlice({
  3. name: 'registration',
  4. initialState: {},
  5. reducers: {
  6. reset() { }
  7. }
  8. })
  9. export { registrationFormSlice }

thunk.ts:

  1. import { Api } from "./api";
  2. import { registrationFormSlice } from "./registration";
  3. type AppDispatch = any;
  4. export const logIn =
  5. (email: string, password: string) =>
  6. async (dispatch: AppDispatch) => {
  7. try {
  8. const { status } = await Api.auth.logIn({ email, password });
  9. if (status === 200) {
  10. dispatch(registrationFormSlice.actions.reset());
  11. }
  12. } catch (error: any) {
  13. console.error(error);
  14. }
  15. };

thunk.test.ts:

  1. import { AnyAction } from 'redux';
  2. import configureStore, { MockStoreCreator } from 'redux-mock-store'
  3. import thunk, { ThunkDispatch } from 'redux-thunk'
  4. import { logIn } from './thunk';
  5. import { Api } from "./api";
  6. import { registrationFormSlice } from './registration';
  7. type RootState = any;
  8. const middlewares = [thunk]
  9. type DispatchExts = ThunkDispatch<RootState, undefined, AnyAction>
  10. const mockStoreCreator: MockStoreCreator<RootState, DispatchExts> =
  11. configureStore<RootState, DispatchExts>(middlewares)
  12. describe('thunk', () => {
  13. afterEach(() => {
  14. jest.restoreAllMocks();
  15. })
  16. test('should pass', () => {
  17. jest.spyOn(Api.auth, 'logIn').mockResolvedValue({ status: 200 } as unknown as Response)
  18. const store = mockStoreCreator();
  19. return store.dispatch(logIn('example@gmail.com', '123')).then(() => {
  20. const actions = store.getActions();
  21. expect(actions).toEqual([registrationFormSlice.actions.reset()])
  22. })
  23. })
  24. })

测试结果:

  1. PASS stackoverflow/76302702/thunk.test.ts (19.876 s)
  2. thunk
  3. should pass (7 ms)
  4. -----------------|---------|----------|---------|---------|-------------------
  5. File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
  6. -----------------|---------|----------|---------|---------|-------------------
  7. All files | 88.24 | 50 | 60 | 87.5 |
  8. api.ts | 66.67 | 100 | 0 | 66.67 | 4
  9. registration.ts | 100 | 100 | 0 | 100 |
  10. thunk.ts | 90.91 | 50 | 100 | 90 | 15
  11. -----------------|---------|----------|---------|---------|-------------------
  12. Test Suites: 1 passed, 1 total
  13. Tests: 1 passed, 1 total
  14. Snapshots: 0 total
  15. 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:

  1. const Api = {
  2. auth: {
  3. async logIn(payload) {
  4. return fetch(&#39;http://localhost:3000/api/login&#39;)
  5. }
  6. }
  7. }
  8. export { Api }

registration.ts:

  1. import { createSlice } from &#39;@reduxjs/toolkit&#39;;
  2. const registrationFormSlice = createSlice({
  3. name: &#39;registration&#39;,
  4. initialState: {},
  5. reducers: {
  6. reset() { }
  7. }
  8. })
  9. export { registrationFormSlice }

thunk.ts:

  1. import { Api } from &quot;./api&quot;;
  2. import { registrationFormSlice } from &quot;./registration&quot;;
  3. type AppDispatch = any;
  4. export const logIn =
  5. (email: string, password: string) =&gt;
  6. async (dispatch: AppDispatch) =&gt; {
  7. try {
  8. const { status } = await Api.auth.logIn({ email, password });
  9. if (status === 200) {
  10. dispatch(registrationFormSlice.actions.reset());
  11. }
  12. } catch (error: any) {
  13. console.error(error);
  14. }
  15. };

thunk.test.ts:

  1. import { AnyAction } from &#39;redux&#39;;
  2. import configureStore, { MockStoreCreator } from &#39;redux-mock-store&#39;
  3. import thunk, { ThunkDispatch } from &#39;redux-thunk&#39;
  4. import { logIn } from &#39;./thunk&#39;;
  5. import { Api } from &quot;./api&quot;;
  6. import { registrationFormSlice } from &#39;./registration&#39;;
  7. type RootState = any;
  8. const middlewares = [thunk]
  9. type DispatchExts = ThunkDispatch&lt;RootState, undefined, AnyAction&gt;
  10. const mockStoreCreator: MockStoreCreator&lt;RootState, DispatchExts&gt; =
  11. configureStore&lt;RootState, DispatchExts&gt;(middlewares)
  12. describe(&#39;thunk&#39;, () =&gt; {
  13. afterEach(() =&gt; {
  14. jest.restoreAllMocks();
  15. })
  16. test(&#39;should pass&#39;, () =&gt; {
  17. jest.spyOn(Api.auth, &#39;logIn&#39;).mockResolvedValue({ status: 200 } as unknown as Response)
  18. const store = mockStoreCreator();
  19. return store.dispatch(logIn(&#39;example@gmail.com&#39;, &#39;123&#39;)).then(() =&gt; {
  20. const actions = store.getActions();
  21. expect(actions).toEqual([registrationFormSlice.actions.reset()])
  22. })
  23. })
  24. })

Test result:

  1. PASS stackoverflow/76302702/thunk.test.ts (19.876 s)
  2. thunk
  3. should pass (7 ms)
  4. -----------------|---------|----------|---------|---------|-------------------
  5. File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
  6. -----------------|---------|----------|---------|---------|-------------------
  7. All files | 88.24 | 50 | 60 | 87.5 |
  8. api.ts | 66.67 | 100 | 0 | 66.67 | 4
  9. registration.ts | 100 | 100 | 0 | 100 |
  10. thunk.ts | 90.91 | 50 | 100 | 90 | 15
  11. -----------------|---------|----------|---------|---------|-------------------
  12. Test Suites: 1 passed, 1 total
  13. Tests: 1 passed, 1 total
  14. Snapshots: 0 total
  15. Time: 21.879 s

huangapple
  • 本文由 发表于 2023年5月22日 10:20:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76302702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定