我在测试一些依赖于异步 thunk 的代码时遇到了一些问题。
这是我的想法:
export const signup = createAsyncThunk(
"auth/signup",
async (payload, { dispatch }) => {
try {
const response = await axios.post(
"https://localhost:5000/auth/signup",
payload
);
const cookies = new Cookies();
cookies.set("token", response.data.token);
cookies.set("email", payload.email);
// TODO: parse JWT fields and set them as cookies
// TODO: return JWT fields here
return { token: response.data.token, email: payload.email };
} catch (err) {
dispatch(
actions.alertCreated({
header: "Uh oh!",
body: err.response.data.error,
severity: "danger",
})
);
throw new Error(err.response.data.error);
}
}
);
这是调用它的测试:
import "@testing-library/jest-dom";
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import configureStore from "redux-mock-store";
import { Provider } from "react-redux";
import thunk from "redux-thunk";
import { signup } from "store/auth-slice";
import { SignUpFormComponent } from "./index";
const mockStore = configureStore([thunk]);
const initialState = {
auth: {
token: null,
email: null,
status: "idle",
},
};
jest.mock("axios", () => {
return {
post: (url, payload) => {
return Promise.resolve({
data: {
token:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjA3MDcwODUwMDk3NDMwMDAsInN1YiI6ImZvb0BleGFtcGxlLmNvbSJ9.iykj3pxsOcFstkS6NCjvjLBtl_hvjT8X9LMZGGsdC28",
},
});
},
};
});
describe("SignUpFormComponent", () => {
it("sends a signup request when the sign up button is clicked", () => {
const store = mockStore(initialState);
render(
<Provider store={store}>
<SignUpFormComponent />
</Provider>
);
const emailInput = screen.getByLabelText("Email address");
userEvent.type(emailInput, "test@example.com");
const passwordInput = screen.getByLabelText("Password");
userEvent.type(passwordInput, "password");
screen.debug();
const submitButton = screen.queryByText("Submit");
fireEvent.click(submitButton);
const actions = store.getActions();
console.log(actions);
console.log(store.getState());
});
});
在我的输出中,我看到以下内容:
console.log
[
{
type: 'auth/signup/pending',
payload: undefined,
meta: {
arg: [Object],
requestId: 'LFcG3HN8lL2aIf_4RMsq9',
requestStatus: 'pending'
}
}
]
at Object.<anonymous> (src/components/signup-form/index.test.js:77:13)
console.log
{ auth: { token: null, email: null, status: 'idle' } }
at Object.<anonymous> (src/components/signup-form/index.test.js:78:13)
但是,如果我尝试通过浏览器自己运行流程,它工作正常,所以我知道至少在浏览器中,thunk 的 FULFILLED
操作正在被调度。
组件正在像这样调度 thunk:
const [registration, setRegistration] = useState({
email: "",
password: "",
});
const dispatch = useDispatch();
const onSubmit = () => {
dispatch(signup(registration));
};
如果我调试测试并在 thunk 中设置一个断点,我实际上可以看到有效负载并一直走到返回,所以这似乎表明它正在工作。
此时我不确定我做错了什么,但我希望在模拟商店的 getActions
中看到已完成的操作,并且我希望看到使用有效负载调用的挂起操作。
答案 0 :(得分:0)
createAsyncThunk
始终异步工作,而您的测试是同步的。 fulfilled
操作将在一两个滴答后发送,但此时您的测试已经结束。
使其异步并等待片刻。
describe("SignUpFormComponent", () => {
it("sends a signup request when the sign up button is clicked", async () => {
// ...
fireEvent.click(submitButton);
await new Promise(resolve => setTimeout(resolve, 5))
const actions = store.getActions();
console.log(actions);
console.log(store.getState());
});
});
我确信有比这更好的方法,但这应该向您展示基本概念。