apollo-client: MockedProvider does not return mocks in a storybook.

Intended outcome: The MockedProvider should work in a storybook environment and return the mock request provided to the MockProvider as per the docs: https://www.apollographql.com/docs/react/api/react/testing/#mockedprovider

Actual outcome: When running a story with MockedProvider, the useQuery hook returns:

{
  error: undefined,
  loading: true,
  data: undefined
}

then it returns:

{
  error: undefined,
  loading: false,
  data: undefined
}

It does not return the mock I provided in my story

How to reproduce the issue:

Here is my story.tsx file

import React from 'react'
import { MockedProvider } from "@apollo/client/testing";
import LatestSells from '~/components/SalesPage/LatestSells'
import { LATEST_SELL_SIGNALS } from '~/common/queries'

export default {
  title: 'Sales page/latest sells',
}


const mocks = [
  {
    request: {
      query: LATEST_SELL_SIGNALS,
      variables: {},
    },
    result: {
      data: {
        dog: {
          name: "Douglas"
        }
      }
    }
  }
]

export const latest_sells = () => {
  return (
    <MockedProvider mocks={mocks} addTypename={false}>
      <LatestSells />
    </MockedProvider>
  )
}

I tried both with and without addTypename={false}

I made my component as simple as possible to troubleshoot, but it doesn’t work even when simplified down to the smallest possible react component.

component:

import React from 'react'
import { useQuery } from '@apollo/client'
import { LATEST_SELL_SIGNALS } from '~/common/queries'

const LatestSells = () => {
  const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS)
  console.log(loading, error, data)
  return null
}

export default LatestSells

Even with the simplest possible setup, this does not work.

Lastly here is my query:

import { gql } from 'apollo-boost'

export const LATEST_SELL_SIGNALS = gql`
  query {
    latestSellSignalsList(orderBy: createdAt_DESC, first: 10) {
      items {
        name
        ticker
        boughtAt
        soldAt
      }
    }
  }
`

I’ve doubled checked that the query console logs correctly and the same in both the story and the actual component.

Versions System: OS: macOS 10.15.6 Binaries: Node: 14.4.0 - /usr/local/bin/node Yarn: 1.22.4 - /usr/local/bin/yarn npm: 6.14.5 - /usr/local/bin/npm Browsers: Chrome: 85.0.4183.121 Firefox: 81.0 Safari: 14.0 npmPackages: @apollo/client: ^3.2.1 => 3.2.1 apollo-boost: ^0.4.9 => 0.4.9 apollo-link: ^1.2.14 => 1.2.14 apollo-link-batch-http: ^1.2.14 => 1.2.14 apollo-link-context: ^1.0.20 => 1.0.20 apollo-link-error: ^1.1.13 => 1.1.13 apollo-utilities: ^1.3.4 => 1.3.4

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 9
  • Comments: 39 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I find this a strange user-behaviour, but I figured it out.

I was testing it with dummy data this entire time because I just wanted to see the data return “something”.

However, apparently if you give the mockProvider a mock that doesn’t 100% match the expected schema, it will just give up and return undefined with no error, warning or anything.

When I replaced my dummy data, with a data matching the exact schema of my request it works corrrectly.

Wasted a lot of time on this detail. Please consider adding an error or warning if the mock doesn’t match the expected return, if this is the intended behaviour.

P.S. I also tried setting my apollo-link and apollo-boost imports to @apollo-client, but that did not affect anything.

Having the same issue. As a workaround you may set the fetchPolicy == “no-cache” in the useQuery options:

const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS, {fetchPolicy: "no-cache"})

I had this exact issue which this fixes, but I don’t want to have to refetch my user both on the server and then again in the component, is there another work around for this?

Edit: After a lot of searching there’s a work around adding defaultOptions parameter to the mocked provider!

<MockedProvider
        mocks={mocks}
        addTypename={false}
        defaultOptions={{ watchQuery: { fetchPolicy: 'no-cache' } }}
      >

Having the same issue. As a workaround you may set the fetchPolicy == “no-cache” in the useQuery options:

const { loading, error, data } = useQuery(LATEST_SELL_SIGNALS, {fetchPolicy: "no-cache"})

Please throw an error when mismatched mock shape causes NO MOCK DATA AT ALL to be supplied. That seems like an important requirement for a test component.

sorry, any updates here?

@benjamn Can second that. This behavior is still the same with @apollo/client@3.3.0-beta.14. It’s actually worse, because apollo doesn’t even throw an error anymore when a mock is not found/matched.

I have the same issue with @apollo/client/testing I have the mocks but the request data comes undefined.

tried every solution but it does not work

@tarehart Thanks for this link. It’s very helpful. I have added __typename to the mocks as I use fragments in queries. It’s not obvious and there is no mention of this in the docs (or I haven’t found).

Getting same issue with @apollo/client@3.3.4 even if mocked data matches exactly query inside component.

Same issue here. A mock call had bit-rotted and broke a story due to a missing query in an updated GraphQL operation. I updated @apollo/client to latest (3.3.13), but still no sensible error message: just loading false, error undefined, data undefined. This is super unhelpful–an error warning of invalid mocks would be much more useful here.

Hi @benjamn. I just tried with @apollo/client”: “^3.3.0-beta.9” but had the same problem @MarkLyck said before. Got it working after setting the result data exactly like the schema of my request.

This is something which needs to be improved. For example, another scenario is when the MockedQuery should contain variables.

This returns undefined:

const mockedQuery = {
  request: {
    query: MY_QUERY,
    variables: {
      example: "someString",
    },
  },
  .
  .
  .
}

but this works fine:

const mockedQuery = {
  request: {
    query: MY_QUERY,
    variables: {
      example: "",
    },
  },
  .
  .
  .
}

This is ridiculous that “variables” values may cause that the whole data in a test is undefined.

Getting the same issue with @apollo/client@3.3.6 and @apollo/client@3.4.0-beta.4 with installed the dependency of @wry/equality@0.3.1 😞

Also found that if the nested mock response does not include __typename, it will also be removed silently.

In my case I had to wait so the request could resolve

import { MockedProvider } from '@apollo/client/testing';
import { act, render, screen } from '@testing-library/react';

beforeEach(async () => {
  render(...)

  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });
});

While fetchPolicy: 'no-cache' will work for most people, I was specifically trying to unit test the caching behavior of my app, so I couldn’t use that fix.

Instead, I took the advice from https://levelup.gitconnected.com/gotchas-using-react-apollo-mockprovider-ec2a22a07e76:

Inject InMemoryCache to show the error message

Using that technique, I was able to fix some subtle problems in my mocked responses which had been breaking my test, and I no longer needed to rely on fetchPolicy: 'no-cache'.

In my case, the SSR turned out to be the problem. I fetch the data on the server-side, then read it from the client-side cache and between the data was undefined. I solved this problem by adding a loading state that satisfies mockProvider.

Stack: Nextjs + apollo + storybook (stories with apollo hook useQuery was undefined). Add loading state to the component and make sure that fetched data is equal to the mocked.

Hi @bastianwegge, thanks for the reply. I noticed that this problem must be somewhere on my side because I cannot reproduce this problem on a mocked project. I will double-check my config and let you know.

I’m also running into issues getting MockedProvider to do anything. I’ve looked at the queries for some time and it’s always just returning undefined for data with no logging as to what might be wrong with my query. This is with @apollo/client ^3.2.5.

@MarkLyck Are you actually still using apollo-boost, apollo-link, apollo-link-batch-http, etc? For the link imports, HttpLink should be imported directly from @apollo/client, and the other links can be imported from @apollo/client/link/core, @apollo/client/link/batch-http, @apollo/client/link/context, and/or @apollo/client/link/error.