【问题标题】:Mocking and testing onError with parameters使用参数模拟和测试 onError
【发布时间】:2021-07-09 10:39:52
【问题描述】:

我正在尝试模拟 useMutation,它有一个名为 onError 的参数。我正在使用它,如下面的代码所示。

每当使用 useRedirectOnErrorMutation 时,带有令牌的标头都会附加到请求中,因此如果令牌无效,则会出现 401 错误响应,我将在 useMutation 附带的 onError 函数中捕获该响应并将用户重定向到登录页面。

export const useRedirectOnErrorMutation = <
    TData = unknown,
    TError = unknown,
    TVariables = void,
    TContext = unknown
>(
    redirectionPath: string,
    key: MutationKey,
    mutationFunction: MutationFunction<TData, TVariables>,
    options?: UseMutationOptions<TData, TError, TVariables, TContext>
): UseMutationResult<TData, TError, TVariables, TContext> => {
    const router = useRouter();
    console.log(useMutation);
    return useMutation(key, mutationFunction, {
        ...options,
        onError: (error) => {
            if (error?.response.status == "401" || error?.response.status == "422") {
                localStorage.removeItem("token");
                localStorage.removeItem("userId");
                router.push(redirectionPath);
            }
        },
    });
};

上面的代码工作得很好,现在我必须以 100% 的覆盖率测试这个函数。

我目前对该功能的测试实现如下。

describe("(when api call gives error", () => {
        it("should return the response", () => {
            const push = jest.fn();

            let onError: (
                error: any,
                variables: any,
                context: any | undefined
            ) => Promise<void> | void;
            // @ts-ignore
            Router.useRouter = jest.fn(() => ({
                push: push,
            }));
            const mockData = { email: "test@test.com", password: "test@1234" };

            // @ts-ignore
            ReactQuery.useMutation = jest.fn(
                (
                    key: MutationKey,
                    mutationFunction: MutationFunction,
                    options: MutateOptions<
                        AxiosResponse<LoginResponse>,
                        AxiosError,
                        LoginValidationValues
                    >
                ) => {
                    console.log(options.onError.arguments);
                    onError = options.onError;
                    return {
                        mutate: jest.fn(() => mockData),
                        isLoading: false,
                    };
                }
            );
            const { result, rerender } = renderHook(() =>
                useRedirectOnErrorMutation("/auth/admin/login", "key", adminLoginAPI)
            );

            rerender();

            act(() => {
                onError({}, {}, {});
            });

            expect(result.current.mutate(mockData)).toEqual(mockData);
            expect(push).toHaveBeenCalled();
        });
    });
});

现在,这里测试的问题是,每次我运行它时,它仍然显示未覆盖的 onError 部分和一条错误消息,指出 error.response 未定义。 我不确定如何在测试中传递 onError 参数。

那是(错误)

onError: (error) => {
                if (error?.response.status == "401" || error?.response.status == "422") {
                    localStorage.removeItem("token");
                    localStorage.removeItem("userId");
                    router.push(redirectionPath);
                }

理想情况下,在由 act 包装的测试中传递一个错误对象应该可以工作,但它也以错误消息告终 onError is not a function

act(()=>{
  onError({response:{status: 401}},{},{})
})

任何帮助将不胜感激!我完全被困在这里了。

【问题讨论】:

  • 请重新表述您的问题。什么工作,什么不工作?它表现如何,您希望它表现如何?
  • 我已经做出了改变!我希望这能提供更多的见解。对于给您带来的不便,我深表歉意。

标签: typescript testing jestjs react-testing-library react-query


【解决方案1】:

我真的不能给你一个具体的答案,也许只是一点建议:

  1. 需要 100% 的测试覆盖率背后的目的是什么?您尝试测试的功能有很多副作用,您必须模拟请求、localStorage、react-router、onError 等内容,剩下的基本上是测试代码而不是实际生产代码。您基本上是在测试 react-query 是否调用 onError 方法,这是 react-query 在内部测试的内容。不要测试第 3 方代码 - 测试您自己的代码。通过集成或端到端测试可以更好地测试此类事情,cypress 是一个很好的工具。

  2. 如果你想测试自定义钩子,我只会模拟 queryFn 的结果,而不是整个突变函数。 nock 对此很有用 - 在 react-query-docs 中甚至还有一个如何做到这一点的示例。 mock-service-worker 是一个在网络级别模拟请求的好工具,如果你想阅读 here,我最近写了一篇关于使用模拟服务工作者测试反应查询的文章。它还链接到带有工作测试的示例存储库。

【讨论】:

  • 但是我怎么确定当遇到错误时,页面会从测试的角度重定向呢?另外,我需要 100% 的覆盖率,因为如果测试没有超过 95%,我们的管道就会失败。关键是,它鼓励我们保持代码质量并处理边缘情况。另外,假设当我模拟 API 响应并发送 401 错误时,onError 部分将被执行,并且它没有错误对象来检查状态。
【解决方案2】:

解决方案是在测试中创建查询客户端时关闭反应重试,否则反应查询将等待下一次重试失败(默认:3 次)并且可能会超时。 https://github.com/tannerlinsley/react-query/discussions/2196#discussioncomment-659468

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 2013-05-06
    • 1970-01-01
    • 2014-05-24
    • 2015-12-04
    • 2020-05-14
    相关资源
    最近更新 更多