【发布时间】:2021-10-14 09:08:09
【问题描述】:
一些背景知识:我有一个在加载时立即调用 useQuery 挂钩的组件。在该查询运行时,我旋转了一个加载微调器。完成后,我会根据数据渲染内容。
我添加了一个useEffect 挂钩,用于监视查询结果并记录数据,这就是我观察到此问题的方式。
为了简化,它的工作方式如下:
export default function MyComponent(props: ???) {
const result = useQuery(INITIAL_DATA_QUERY, { variables: { id: 1 } });
React.useEffect(() => console.log(JSON.stringify({
loading: result.loading,
data: result.data,
error: result.error,
})), [result]);
if (result.loading) return <LoadingScreen message="Fetching data..."/>;
else if (result.error) return <ErrorPage/>
else return <Stuff info={result.data}> // omitted because it's unimportant to the issue
}
当我在野外运行这个组件时,一切都按预期工作。它通过 Apollo 使用 GraphQL 到达端点,根据结果做出渲染决策等。
当我尝试模拟请求时,result.data 和 result.error 字段永远不会改变,即使 result.loading 字段会改变。我正在使用react-testing-library 运行测试。
我的测试如下所示:
it("should load the data then render the page", () => {
const mocks = [{
request: {
query: INITIAL_DATA_QUERY,
variables: { id: 1 },
},
newData: jest.fn(() => ({
data: {
firstName: "Joe",
lastName: "Random",
}
}))
}];
const mockSpy = mocks[0].newData;
render(
<MockedProvider mocks={mocks} addTypename={false}>
<MyComponent/>
</MockedProvider>
)
// Is it a loading view
expect(result.asFragment()).toMatchSnapshot(); // Passes just fine, and matches expectations
// Wait until the mock has been called once
await waitFor(() => expect(mockSpy).toHaveBeenCalled(1)) // Also passes, meaning the mock was called
// Has the page rendered once the loading mock has finished
expect(result.asFragment()).toMatchSnapshot(); // Passes, but the page has rendered without any of the data
})
问题是这样的:当我运行这个测试时,所有三个测试都按预期通过,但在最终片段中,我渲染的组件中的数据丢失了。我确信正在调用模拟,因为我添加了一些记录器语句来检查。
真正令人困惑的部分是调用 mock 时的 loading、data 和 error 值。我有一个useEffect 语句在它们中的任何一个发生变化时记录它们的值,当我运行测试时,输出如下所示:
{ loading: true, data: undefined, error: undefined }
{ loading: false, data: undefined, error: undefined }
这意味着正在调用钩子并开始加载,但是一旦加载结束,加载过程中发生的任何事情都不会返回任何数据,也不会产生任何错误。
有人知道我的问题可能是什么吗?我已经看了八种方式到星期天,但无法弄清楚。
【问题讨论】:
标签: javascript reactjs mocking apollo react-testing-library