如何使用 react-hooks-testing-library 测试自定义 async/await 钩子

Posted

技术标签:

【中文标题】如何使用 react-hooks-testing-library 测试自定义 async/await 钩子【英文标题】:How to test custom async/await hook with react-hooks-testing-library 【发布时间】:2019-12-21 01:51:45 【问题描述】:

我创建了一个自定义反应钩子,它应该处理所有不太重要的 api 请求,我不想将其存储在 redux 状态。 Hook 工作正常,但我无法测试它。我的测试设置是 jest 和酵素,但我决定在这里也试试 react-hooks-testing-library

到目前为止,我尝试的是首先使用 fetch-mock 库模拟 fetch 请求,效果很好。接下来,我使用来自 react-hooks-testing-library 的 renderHook 方法渲染钩子。不幸的是,看起来我不太了解waitForNextUpdate 方法。

这就是我的钩子的样子。

使用Api挂钩

export function useApi<R, B = undefined>(
    path: string,
    body: B | undefined = undefined,
    method: HttpMethod = HttpMethod.GET
): ResponseStatus<R> 
    const [response, setResponse] = useState();
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [error, setError] = useState<string | boolean>(false);

    useEffect(() => 
        const fetchData = async (): Promise<void> => 
            setError(false);
            setIsLoading(true);
            try 
                const result = await callApi(method, path, body);
                setResponse(result);
             catch (errorResponse) 
                setError(errorResponse);
            

            setIsLoading(false);
        ;

        fetchData();
    , [path, body, method]);

    return  response, isLoading, error ;

Hook 可以采用我想测试的 3 种不同的状态组合。不幸的是,我不知道怎么做。

加载数据:

 response: undefined, isLoading: true, error: false 

加载的数据:

 response: R, isLoading: false, error: false 

错误:

 response: undefined, isLoading: false, error: true 

这就是我的测试此时的样子:

import fetchMock from 'fetch-mock';
import  useApi  from './hooks';
import  renderHook  from '@testing-library/react-hooks';

test('', async () => 
    fetchMock.mock('*', 
        returnedData: 'foo'
    );

    const  result, waitForNextUpdate  = renderHook(() => useApi('/data-owners'));

    console.log(result.current);

    await waitForNextUpdate();

    console.log(result.current);
);

callApi 函数

/**
 * Method to call api.
 *
 * @param HttpMethod method - Request type.
 * @param string path - Restful endpoint route.
 * @param any body - Request body data.
 */
export const callApi = async (method: HttpMethod, path: string, body: any = null) => 
    // Sends api request
    const response = await sendRequest(method, path, body);
    // Checks response and parse to the object
    const resJson = response ? await response.json() : '';

    if (resJson.error) 
        // If message contains error, it will throw new Error with code passed in status property (e.g. 401)
        throw new Error(resJson.status);
     else 
        // Else returns response
        return resJson;
    
;

【问题讨论】:

react-hooks-testing-library 作者在这里。您对renderHookwaitForNextUpdate 的使用看起来是正确的,所以我认为要么发生批处理问题,要么存在阻止更新发生的其他原因。测试失败时以及从控制台日志中看到的实际错误是什么? 【参考方案1】:

你做的很好。现在,您需要使用 expect 进行测试。

const value = ...
expect(result.current).toEqual(value)

【讨论】:

以上是关于如何使用 react-hooks-testing-library 测试自定义 async/await 钩子的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?