我仅获得加载状态,并且在测试中未定义数据。我不知道为什么我要遵循给定示例中的所有内容。请帮忙。
测试文件。当我等待该行执行await wait(() => getByTestId('edit-category'));
时。它给出了未定义的查询响应数据。
错误:TypeError: Cannot read property 'getCategory' of undefined
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>
这不起作用。我没有验证的查询工作正常。突变也可以正常工作。我对此只有问题。当我必须像这样通过变通时。
答案 0 :(得分:1)
我遇到了类似的问题。这是我解决问题的方法。
首先,按照@mikaelrs 和 the docs 的建议等待查询解析:
await new Promise(resolve => setTimeout(resolve, 0));
执行此操作后,loading
属性为 false
,但 data
仍为 undefined
。我发现我的模拟结果对象缺少一个属性。一旦我将缺少的属性添加到模拟结果中,data
就会按预期填充。
答案 1 :(得分:0)
我要等待MockedProvider
的加载状态通过的方法是使用wait
中的waait
函数。这实际上也是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
的{{1}}函数等待在加载状态切换为true后出现的元素。
例如
wait