使用 MockedProvider 进行测试时使用 Apollo 突变更新存储

Posted

技术标签:

【中文标题】使用 MockedProvider 进行测试时使用 Apollo 突变更新存储【英文标题】:Update store with Apollo mutation when testing with MockedProvider 【发布时间】:2019-03-23 03:48:18 【问题描述】:

我正在尝试测试在运行突变后应该使用新数据更新的组件。我在下面发布了示例代码。你可以找到它on GitHub as runnable repository as well。

不幸的是,我没有找到一种方法在突变后实际更新MockedProvider 的存储数据。当您运行测试时,您可以看到正在执行突变并且组件在此之后被渲染。但是由于突变没有做任何事情,所以没有添加新的待办事项。

谁能告诉我在使用MockedProvider 时如何通过突变更改数据?

测试查询和变异:

const TODOS_QUERY = gql`
  query todos 
    todos 
      title
    
  
`

const ADD_TODO_MUTATION = gql`
  mutation addTodo($title: String!) 
    addTodo(title: $title)
  
`;

测试组件:

const Component = () => (
  <Query query=TODOS_QUERY>
    
      ( data ) => 
        console.log('render'); return (
        <Mutation mutation=ADD_TODO_MUTATION>
          
            addTodo => (
              <div>
                <button onClick=() =>  console.log('addTodo'); addTodo( variables:  title: 'My new todo'  ) >
                  Click me to add a todo!
                </button>

                
                  (data.todos || []).map(( title , index) => (
                    <div key=index className="todo-item">
                      title
                    </div>
                  ))
                
              </div>
            )
          
        </Mutation>
      )
    
  </Query>
);

测试实现。这会使用 Enzyme 挂载组件,模拟单击按钮执行突变并等待组件再次渲染。

it('renders without crashing', async () => 
  const mocks = [
    
      request: 
        query: TODOS_QUERY,
      ,
      result: 
        data: 
          todos: [
            
              title: 'An old todo',
            ,
          ],
        ,
      ,
    ,
    
      request: 
        query: ADD_TODO_MUTATION,
        variables: 
          title: 'My new todo',
        ,
      ,
      result: 
        data: 
          addTodo: null,
        ,
      ,
    ,
  ];

  const wrapper = mount(
    <MockedProvider mocks=mocks addTypename=false>
      <Component />
    </MockedProvider>
  );

  await wait(100);
  wrapper.update();

  console.log(wrapper.debug())

  expect(wrapper.contains('An old todo')).toBe(true);
  expect(wrapper.contains('My new todo')).toBe(false);
  wrapper.find('button').simulate('click');

  await wait(100);
  wrapper.update();

  console.log(wrapper.debug())

  expect(wrapper.contains('An old todo')).toBe(true);
  expect(wrapper.contains('My new todo')).toBe(true);
);

非常感谢您的帮助!

【问题讨论】:

【参考方案1】:

MockedProvider 接受一个 cache 属性,您可以将自己的缓存传递给它(与您在初始化 ApolloClient 时使用的相同)。这应该会在测试中为您提供自动缓存更新。

您可能需要删除addTypeName=false 才能使其工作,并提供包括__typenames 在内的模拟。

https://www.apollographql.com/docs/react/api/react-testing/

【讨论】:

以上是关于使用 MockedProvider 进行测试时使用 Apollo 突变更新存储的主要内容,如果未能解决你的问题,请参考以下文章

阿波罗的 MockedProvider 没有明确警告丢失的模拟

如何模拟 useApolloClient 钩子?

在 jest-react 中使用 MockedProvider 会导致错误“查询没有更多的模拟响应”

apollo MockedProvider + Storybook 不工作

reactjs / jest:无法使用 MockedProvider 用数据填充 react-apollo 组件?

通过 apollo 客户端测试使用查询和订阅的反应组件