简体   繁体   English

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

[英]React Apollo Testing is not working. Query data is always coming undefined

I am getting loading state only and data as undefined in testing.我在测试中仅获取加载状态和未定义的数据。 I don't know why I am following everything in the given example.我不知道为什么我要遵循给定示例中的所有内容。 Please help.请帮忙。

Testing file.测试文件。 When i am waiting thsi line toexecute await wait(() => getByTestId('edit-category'));当我等待这条线执行时await wait(() => getByTestId('edit-category')); . . It is giving response data of query as undefined.它将查询的响应数据提供为未定义。 Error: TypeError: Cannot read property 'getCategory' of undefined Line 34 on editConatinerCategory.tsx => category={data!.getCategory!}错误: TypeError: Cannot read property 'getCategory' of undefined editConatinerCategory.tsx TypeError: Cannot read property 'getCategory' of undefined第 34 行的TypeError: Cannot read property 'getCategory' of undefined => 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自定义渲染.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编辑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>
  );
});

Edit: I tried @mikaelrs solution which is passed match.编辑:我尝试了通过匹配的@mikaelrs 解决方案。 But it is not working.但它不起作用。 I also tried to pass id:1 as fixed.我还尝试将 id:1 作为固定值传递。 But it is still giving error.但它仍然给出错误。

 <GetCategoryComponent
      variables={{
        id:1
      }}
    >
...rest of code.
</GetCategoryComponent>

This is not working.这是行不通的。 My query without veriable is working fine.我没有验证的查询工作正常。 Mutation is also working fine.突变也工作正常。 I am having only problem with this.我只有这个问题。 When i have to pass like varible like this.当我必须像这样通过变量时。

What I do to wait for the loading state of the MockedProvider to pass is to use the wait function from waait .为了等待MockedProvider的加载状态通过,我所做的是使用来自waaitwait函数。 This is actually what Apollo recommends as well.这实际上也是Apollo推荐的。

So in your test you would do:所以在你的测试中你会这样做:

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()
  });
});

Another solution is to use react-testing-library s wait function to wait for an element that would be present after the loading state switches to true.另一种解决方案是使用react-testing-librarywait函数来等待加载状态切换为 true 后出现的元素。

For instance例如

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()
  });
});

I faced a similar issue.我遇到了类似的问题。 Here is how I resolved my issue.这是我如何解决我的问题。

First, wait for the query to resolve, as recommended by @mikaelrs and the docs :首先,按照@mikaelrs 和文档的建议,等待查询解析:

await new Promise(resolve => setTimeout(resolve, 0));

After doing that, the loading property was false , but data was still undefined .这样做之后, loading属性为false ,但data仍然是undefined I discovered that my mock result object was missing a property .我发现我的模拟结果对象缺少一个属性 Once I added that missing property to the mock result, the data was populated as expected.一旦我将该缺失的属性添加到模拟结果中, data按预期填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM