React Apollo 测试不起作用。查询数据总是未定义
Posted
技术标签:
【中文标题】React Apollo 测试不起作用。查询数据总是未定义【英文标题】:React Apollo Testing is not working. Query data is always coming undefined 【发布时间】:2019-08-24 22:00:27 【问题描述】:我只得到加载状态和测试中未定义的数据。我不知道为什么我要遵循给定示例中的所有内容。请帮忙。
测试文件。当我等待这条线执行await wait(() => getByTestId('edit-category'));
。它给出了未定义的查询响应数据。
错误:TypeError: Cannot read property 'getCategory' of undefined
第 34 行 editConatinerCategory.tsx
=> category=data!.getCategory!
import React from 'react';
import gql from 'graphql-tag';
import cleanup, wait from 'react-testing-library';
import customRender from '../../../test-utils/customRender';
import EditCategoryContainer from './Container';
afterEach(() =>
cleanup();
console.error;
);
console.error = jest.fn();
const getCategoryMock =
request:
query: gql`
query getCategory($id: Int!)
getCategory(id: $id)
id
name
active
position
`,
variables:
id: 1
,
result:
data:
getCategory:
id: 1,
name: 'category',
active: true,
position: 1
;
describe('create edit category module', () =>
test('Rendering correct', async () =>
const container, debug, getByTestId = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(() => getByTestId('edit-category'));
await wait(() => expect(container).toMatchSnapshot());
//Getting this TypeError: Cannot read property 'getCategory' of undefined. Because i am data as undefined from my query response
);
);
CustomRender.tsx
import React from 'react';
import render from 'react-testing-library';
import MockedProvider, MockedResponse from 'react-apollo/test-utils';
import Router, Switch from 'react-router-dom';
import createMemoryHistory from 'history';
export const customRender = (
node: JSX.Element | null,
mocks?: MockedResponse[],
route = '/',
history = createMemoryHistory( initialEntries: [route] )
=
) =>
return
history,
...render(
<MockedProvider mocks=mocks addTypename=false>
<Router history=history>
<Switch>node</Switch>
</Router>
</MockedProvider>
)
;
;
EditCategoryContainer.tsx
import React from 'react';
import withRouter from 'react-router';
import Spin from 'antd';
import
AddCategoryComponent,
GetCategoryComponent
from '../../../generated/graphql';
import EditCategory from './Edit';
import LoadingComponent from '../../../components/LoadingComponent';
export const EditCategoryContainer = withRouter(( history, match ) =>
const id: number = parseInt(match.params.id, 10);
return (
<GetCategoryComponent
variables=
id
>
( data, loading: getCategoryLoading ) =>
console.log(getCategoryLoading, 'getCategoryLoading');
if (getCategoryLoading)
return <LoadingComponent />;
if (data && !data.getCategory)
return <div>Category not found!</div>;
console.log(data);
return (
<AddCategoryComponent>
(addCategory, loading, error ) =>
return (
<EditCategory
data-testid="edit-category"
category=data!.getCategory!
loading=loading || getCategoryLoading
onSubmit=values =>
addCategory( variables: values ).then(() =>
history.push('/dashboard/categories');
);
/>
);
</AddCategoryComponent>
);
</GetCategoryComponent>
);
);
编辑: 我尝试了通过匹配的@mikaelrs 解决方案。但它不起作用。我也尝试通过 id:1 固定。但它仍然给出错误。
<GetCategoryComponent
variables=
id:1
>
...rest of code.
</GetCategoryComponent>
这不起作用。我没有验证的查询工作正常。突变也可以正常工作。我只有这个问题。当我必须像这样通过变量时。
【问题讨论】:
【参考方案1】:等待MockedProvider
的加载状态通过的方法是使用waait
中的wait
函数。这实际上也是Apollo
推荐的。
所以在你的测试中你会这样做:
import React from 'react';
import gql from 'graphql-tag';
import cleanup from 'react-testing-library';
import wait from 'waait'
import customRender from '../../../test-utils/customRender';
import EditCategoryContainer from './Container';
afterEach(() =>
cleanup();
);
const getCategoryMock =
request:
query: gql`
query getCategory($id: Int!)
getCategory(id: $id)
id
name
active
position
`,
variables:
id: 1
,
result:
data:
getCategory:
id: 1,
name: 'category',
active: true,
position: 1
;
describe('create edit category module', () =>
test('Rendering correct', async () =>
const container, debug = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(0);
// Your loading state should be false after this, and your component should
// get it's data from apollo for you to do any assertion you would like to
// after this point. To see that the component is rendered with data invoke
// the debug function from react-testing-library after this point
debug();
expect(container).toMatchSnapshot()
);
);
另一种解决方案是使用react-testing-library
s wait
函数等待加载状态切换为true后将出现的元素。
例如
describe('create edit category module', () =>
test('Rendering correct', async () =>
const container, debug, queryByText = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(()=> queryByText("Some Data"));
// Your loading state should be false after this, and your component should
// get it's data from apollo for you to do any assertion you would like to
// after this point
expect(container).toMatchSnapshot()
);
);
【讨论】:
我正在使用 react-testing-library 等待功能。但它仍然给我未定义, 但是你在 await 函数内部做了一个期望。你能尝试等待'waait'的等待,这是从阿波罗测试最终状态的推荐方法。 apollographql.com/docs/react/recipes/… 也从 wait 库中尝试过等待。我仍然遇到同样的错误。 好的,我会试试的,我会告诉你的。 什么都试过了。最后,从 wait 包中添加 wait 起到了神奇的作用。我所要做的就是包括等待等待(0)。非常感谢@mikaelrs【参考方案2】:我遇到了类似的问题。以下是我解决问题的方法。
首先,按照@mikaelrs 和the docs 的建议,等待查询解决:
await new Promise(resolve => setTimeout(resolve, 0));
这样做之后,loading
属性为false
,但data
仍为undefined
。我发现我的模拟结果对象缺少属性。一旦我将缺少的属性添加到模拟结果中,data
就会按预期填充。
【讨论】:
以上是关于React Apollo 测试不起作用。查询数据总是未定义的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React + Apollo GraphQL 中查询先前查询的结果?