T
TanStack13mo ago
extended-salmon

Mocking useMutation returned value

We are testing our App component and we required to mock a hook:
const useTodos = () => {
const queryClient = useQueryClient();

const { data, error, isLoading } = useQuery<Array<Todo>, Error>({
queryKey: ["todos"],
queryFn: service.fetchTodos,
});

const mutation = useMutation({
mutationFn: service.updateTodo,
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ["todos"] });
},
});

return { data, error, isLoading, mutation };
};
const useTodos = () => {
const queryClient = useQueryClient();

const { data, error, isLoading } = useQuery<Array<Todo>, Error>({
queryKey: ["todos"],
queryFn: service.fetchTodos,
});

const mutation = useMutation({
mutationFn: service.updateTodo,
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ["todos"] });
},
});

return { data, error, isLoading, mutation };
};
We mocked it with vitest and we call it on tests:
vi.mock("@application/hooks/updateTodo");

---

it("should renders a Spinner when it is loading", () => {
vi.mocked(useTodos).mockReturnValue({
data: undefined,
error: null,
isLoading: true,
mutation: { mutate: vi.fn() },
});

render(<App />);

expect(screen.getByText("Loading...")).toBeInTheDocument();
});
vi.mock("@application/hooks/updateTodo");

---

it("should renders a Spinner when it is loading", () => {
vi.mocked(useTodos).mockReturnValue({
data: undefined,
error: null,
isLoading: true,
mutation: { mutate: vi.fn() },
});

render(<App />);

expect(screen.getByText("Loading...")).toBeInTheDocument();
});
However, we have a typing problem with the mock:
Type '{ mutate: Mock<Procedure>; }' is not assignable to type 'UseMutationResult<void, Error, UpdateTodoProps, unknown>'.
Type '{ mutate: Mock<Procedure>; }' is not assignable to type 'Override<MutationObserverSuccessResult<void, Error, UpdateTodoProps, unknown>, { mutate: UseMutateFunction<void, Error, UpdateTodoProps, unknown>; }> & { ...; }'.
Type '{ mutate: Mock<Procedure>; }' is missing the following properties from type 'Override<MutationObserverSuccessResult<void, Error, UpdateTodoProps, unknown>, { mutate: UseMutateFunction<void, Error, UpdateTodoProps, unknown>; }>': data, error, variables, isError, and 10 more.ts(2322)
updateTodo.ts(20, 36): The expected type comes from property 'mutation' which is declared here on type '{ data: Todo[] | undefined; error: Error | null; isLoading: boolean; mutation: UseMutationResult<void, Error, UpdateTodoProps, unknown>; }'
(property) mutation: UseMutationResult<void, Error, UpdateTodoProps, unknown>
Type '{ mutate: Mock<Procedure>; }' is not assignable to type 'UseMutationResult<void, Error, UpdateTodoProps, unknown>'.
Type '{ mutate: Mock<Procedure>; }' is not assignable to type 'Override<MutationObserverSuccessResult<void, Error, UpdateTodoProps, unknown>, { mutate: UseMutateFunction<void, Error, UpdateTodoProps, unknown>; }> & { ...; }'.
Type '{ mutate: Mock<Procedure>; }' is missing the following properties from type 'Override<MutationObserverSuccessResult<void, Error, UpdateTodoProps, unknown>, { mutate: UseMutateFunction<void, Error, UpdateTodoProps, unknown>; }>': data, error, variables, isError, and 10 more.ts(2322)
updateTodo.ts(20, 36): The expected type comes from property 'mutation' which is declared here on type '{ data: Todo[] | undefined; error: Error | null; isLoading: boolean; mutation: UseMutationResult<void, Error, UpdateTodoProps, unknown>; }'
(property) mutation: UseMutationResult<void, Error, UpdateTodoProps, unknown>
What's the right way to mock it?
1 Reply
harsh-harlequin
harsh-harlequin13mo ago
useMutation returns more than just the mutate function. Either you mock everything you return, or you don't return the full mutation.

Did you find this page helpful?