Mike-Gibson / mock-apollo-client

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

Cannot test as a subscribeToMore subscription #57

Closed JonathanGafar closed 7 months ago

JonathanGafar commented 7 months ago

I've got a component that makes a lazy query, takes the subscribeToMore function returned and calls it in a useEffect. The GQL documents passed to the lazy query and subscribeToMore function are different. I keep getting this warning: "Warning: mock-apollo-client - Mock subscription has no observer, this will have no effect".

Here is a quick example of what I mean:

const [
  getUsers,
  { data: users, subscribeToMore: usersSubscribeToMore }
] = useGetProjectsLazyQuery()

useEffect(() => {
  if (!users) return

  getUsers({
    fetchPolicy: 'network-only',
    variables: {
      // some variables
    }
  })
}, [])

useEffect(() => {
  if (
    !featuredProjects
  ) {
    return
  }

    usersSubscribeToMore<UserUpdatedSubscription>({
      document: UserUpdatedDocument,
      updateQuery: (prev, { subscriptionData }) => {
        // some logic
      }
    })

})

My test looks something like this:

let mockClient: MockApolloClient
let mockSubscription: IMockSubscription

describe('some tests', () => {
    beforeEach(() => {
    mockClient = createMockClient()
    mockSubscription = createMockSubscription()

    mockClient.setRequestHandler(
      GetUsersDocument,
      // some handler
    )

    mockClient.setRequestHandler(UserUpdatedDocument, () => mockSubscription)
  })

  test('some test', async () => {
    render(
      <ApolloProvider client={mockClient}>
        <Provider store={store}>
          <Users />
        </Provider>
      </ApolloProvider>
    )

    act(() => {
      mockSubscription.next({
        data: { users: // some data }
      })
    })

    await waitFor(() => {
      // expect some stuff
    })
  })

})

EDIT: I was able to test this by treating it as a query rather than following the strategy provided in the docs for subscriptions.

Mike-Gibson commented 7 months ago

I quickly put together a test using the set up you described above, and it seems to be working as expected for me.

From the details above, I wonder if there's a race condition in your full code, where you're calling mockSubscription.next before the subscribeToMore function has been called? As that would explain the warning you're seeing - Mock subscription has no observer, this will have no effect as apollo client hasn't subscribed yet.

If you think that's not the case, and there is an issue in the mock-apollo-client library, would be great if you could provide a full working sample to help diagnose the issue.

JonathanGafar commented 7 months ago

You were absolutely correct that it was a race condition in my code. I appreciate your time. I'll close this issue. Thanks.

Mike-Gibson commented 7 months ago

Glad to hear you got it working.