反应阿波罗测试不起作用。查询数据总是未定义

Vik*_*ini 1 reactjs react-apollo react-testing-library

我在测试中仅获取加载状态和未定义的数据。我不知道为什么我要遵循给定示例中的所有内容。请帮忙。

测试文件。当我等待这条线执行时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

  });
});
Run Code Online (Sandbox Code Playgroud)

自定义渲染.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>
    )
  };
};
Run Code Online (Sandbox Code Playgroud)

编辑CategoryContainer.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>
  );
});

Run Code Online (Sandbox Code Playgroud)

编辑:我尝试了通过匹配的@mikaelrs 解决方案。但它不起作用。我还尝试将 id:1 作为固定值传递。但它仍然给出错误。

 <GetCategoryComponent
      variables={{
        id:1
      }}
    >
...rest of code.
</GetCategoryComponent>
Run Code Online (Sandbox Code Playgroud)

这是行不通的。我没有验证的查询工作正常。突变也工作正常。我只有这个问题。当我必须像这样通过变量时。

mik*_*lrs 5

我等待MockedProvider传递的加载状态是使用wait函数 from 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()
  });
});
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是使用react-testing-libraryswait函数等待加载状态切换为 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()
  });
});
Run Code Online (Sandbox Code Playgroud)