React Apollo 测试不工作。查询数据总是未定义
React Apollo Testing is not working. Query data is always coming undefined
我在测试中只获取加载状态和未定义的数据。我不知道为什么我要遵循给定示例中的所有内容。请帮忙。
测试文件。当我在等待这条线执行时 await wait(() => getByTestId('edit-category'));
。它将查询的响应数据提供为未定义。
错误:TypeError: Cannot read property 'getCategory' of undefined
editConatinerCategory.tsx
上的第 34 行 => 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>
这是行不通的。我没有验证的查询工作正常。突变也工作正常。我对此只有问题。当我必须像这样通过变量时。
我等待 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()
});
});
我遇到了类似的问题。这是我解决问题的方法。
首先,按照@mikaelrs 和the docs:
的建议,等待查询解决
await new Promise(resolve => setTimeout(resolve, 0));
这样做之后,loading
属性 是 false
,但 data
仍然是 undefined
。我发现我的 mock 结果对象缺少 属性。一旦我将缺少的 属性 添加到模拟结果中,data
就会按预期填充。
我在测试中只获取加载状态和未定义的数据。我不知道为什么我要遵循给定示例中的所有内容。请帮忙。
测试文件。当我在等待这条线执行时 await wait(() => getByTestId('edit-category'));
。它将查询的响应数据提供为未定义。
错误:TypeError: Cannot read property 'getCategory' of undefined
editConatinerCategory.tsx
上的第 34 行 => 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>
这是行不通的。我没有验证的查询工作正常。突变也工作正常。我对此只有问题。当我必须像这样通过变量时。
我等待 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()
});
});
我遇到了类似的问题。这是我解决问题的方法。
首先,按照@mikaelrs 和the docs:
的建议,等待查询解决await new Promise(resolve => setTimeout(resolve, 0));
这样做之后,loading
属性 是 false
,但 data
仍然是 undefined
。我发现我的 mock 结果对象缺少 属性。一旦我将缺少的 属性 添加到模拟结果中,data
就会按预期填充。