Mike-Gibson / mock-apollo-client

Helps unit test components which use the Apollo Client.
MIT License
117 stars 15 forks source link

[REQUEST] handle multiple mock query #10

Closed deckyfx closed 4 years ago

deckyfx commented 4 years ago

is it possible to swt request handle to handle multiple query?

On side note, is it possible to handle Apollo Subscribe?

Mike-Gibson commented 4 years ago

Hi @deckyfx

I'm not sure I fully understand when you say

swt request handle to handle multiple query?

If you mean different GraphQL requests, then this can be done by, e.g.

mockClient.setRequestHandler(
    GET_DOG_QUERY,
    () => Promise.resolve({ data: { dog: { id: 1, name: 'Rufus', breed: 'Poodle' } } }));

mockClient.setRequestHandler(
    GET_CAT_QUERY,
    () => Promise.resolve({ data: { cat: { id: 1, name: 'Fluffy', breed: 'Persian' } } }));

If you mean multiple requests for the same GraphQL query then it's also possible for example when using jest:

const requestHandler = jest.fn();
requestHandler.mockResolvedValueOnce({ data:  { dog: { id: 1, name: 'Rufus', breed: 'Poodle' } } });
requestHandler.mockResolvedValueOnce({ data:  { dog: { id: 2, name: 'Fred', breed: 'Terrier' } } });

mockClient.setRequestHandler(GET_DOG_QUERY, requestHandler);

which will return Rufus for the first request of GET_DOG_QUERY and Fred for the second. There's also a library like jest-when which would allow you to set up the request handler to return a specific response based on the query parameters rather than just relying on the order in which the queries are called.

Does that answer your question?

As for

is it possible to handle Apollo Subscribe?

I haven't actually tried to see what happens when subscriptions are used with mock-apollo-client. Reading the docs makes me think that it might not work - and the API allows only a single response to be configured via Promises. The API would probably have to change to support the observable pattern/allow triggering of responses being returned. Please give it a go and let me know what happens - would be interested to know!

deckyfx commented 4 years ago

Yeah you helped me a lot, thank you for your time.

rhishikeshj commented 3 years ago

Hi, I am also trying out this library for mocking apollo client calls in my tests and using them to test some custom hooks that I have. I am also using the React native hooks testing library for testing the hooks rather than having components in tests. My custom hook looks like this

import { useQuery } from '@apollo/react-hooks'
import { GET_USER } from '../../src/services/auth/AuthService'
import { client } from '../../src/services/apollo/hydra' // this is mocked out in tests with createMockClient()

export function useGetUser () {
    const { data, refetch, error } = useQuery(GET_USER, {client})
    return data
}

My test looks like this

  it('should initialise correctly...', async () => {
    const queryHandler = jest.fn();
    queryHandler.mockResolvedValueOnce({
        data: {
          user: {
            id: 'abcd',
            email: 'old-email@a.com',
          }
        }
      });

    queryHandler.mockResolvedValueOnce({
        data: {
          user: {
            id: 'abcd',
            email: 'updated-email@a.com',
          }
        }
      });
    client.setRequestHandler(GET_USER, queryHandler);
    const { result, waitForNextUpdate, rerender } = renderHook(() => useGetUser());
    await waitForNextUpdate();
    expect(newUserData.data).toEqual(result.current);
    act(() => {
        rerender();
    });
    expect(queryHandler).toBeCalledTimes(2);

Unfortunately it seems that my queryHandler is only called once, even though I have explicitly re-rendered the hook and also set 2 different values for the queryHandler as prescribed here.

Can someone help me understand what I am missing here ? Is my understanding about how hooks and useQuery works flawed ?

Mike-Gibson commented 3 years ago

Hi @rhishikeshj

Is this separate to #35 ? If so, please open a new issue and we can take a look. A new issue will just help keep track of things as this issue is now closed. Thanks!

rhishikeshj commented 3 years ago

Hi @Mike-Gibson So apparently this is due to my mis-understanding of the way in which Apollo's useQuery works. I assumed that with a fetchPolicy of no-cache it would hit the server on every render So this is not the case. For forcing a refetch, refetch and polling are the only 2 options if I understand correctly.

Some more details about the related problem : https://community.apollographql.com/t/relation-between-re-render-and-usequery/462