apollo-client: Mocking UseLazyQuery does not return data
Intended outcome: After setting up MockedProvider with query mocks, uselazyquery hook should return mocked data after loading state.
Actual outcome: Data is undefined, and no query results are returned
How to reproduce the issue:
/**
* @jest-environment jsdom
*/
import {
render, wait
} from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import gql from 'graphql-tag';
import React, {useEffect} from 'react'
import { useLazyQuery } from '@apollo/react-hooks';
import '@testing-library/jest-dom/extend-expect';
export const QUERY = gql`
query BLAH($id: Int) {
investment(id: $id) {
id
}
}
`;
const Component = () => {
const
[fetchQuery, {loading, error, data, refetch, called }]
= useLazyQuery(QUERY, {
variables: {
id: "suchandsuch"
}
});
useEffect(() => {
fetchQuery()
}, [fetchQuery])
if(loading) return "loading"
if(data) return "yes dice"
if(called) return "called"
return 'no dice'
}
describe("Can UseLazyQuery", () => {
let component;
beforeEach(() => {
const mocks = [
{
request: {
query: QUERY,
variables: {
id: "suchandsuch"
}
},
result: {
data: true
}
}
]
component = render(
<MockedProvider mocks={mocks} addTypename={false}>
<Component />
</MockedProvider>
)
})
it("has dice", async () => {
const { getByText } = component;
await wait(() => {
expect(getByText('yes dice')).toBeInTheDocument();
});
})
})
TestingLibraryElementError: Unable to find an element with the text: yes dice. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
called
</div>
</body>
65 | const { getByText } = component;
66 | await wait(() => {
> 67 | expect(getByText('yes dice')).toBeInTheDocument();
| ^
68 | });
69 | })
70 | })
Versions
npx: installed 1 in 1.939s
System: OS: macOS Mojave 10.14.6 Binaries: Node: 12.11.1 - ~/.nvm/versions/node/v12.11.1/bin/node Yarn: 1.22.4 - ~/code/project-mercury/node_modules/.bin/yarn npm: 6.11.3 - ~/.nvm/versions/node/v12.11.1/bin/npm Browsers: Chrome: 84.0.4147.125 Firefox: 77.0.1 Safari: 13.1.2 npmPackages: @apollo/client: ^3.1.3 => 3.1.3 @apollo/react-hooks: ^4.0.0 => 4.0.0 @apollo/react-testing: ^4.0.0 => 4.0.0 apollo-boost: ^0.4.7 => 0.4.7 apollo-cache-inmemory: ^1.6.5 => 1.6.5
Other Mentions I believe these issues were related https://github.com/apollographql/react-apollo/issues/3899 https://spectrum.chat/apollo/testing/how-to-test-uselazyquery~c3a55a74-2a15-4c6d-a0f7-e11966c02479
Hacky Workaround I was playing with
jest.mock('@apollo/react-hooks')
import { useLazyQuery } from '@apollo/react-hooks';
useLazyQuery.mockImplementation((query, {variables: initialVariables}) => {
const [attributes, setAttributes] = useState({})
const [mockCount, setMockCount] = useState(0)
const verifyGraphQLMock = ({variables: passedVariables}) => {
const variables = passedVariables || initialVariables
expect(mocks[mockCount]).toBeTruthy()
expect(query).toEqual(mocks[mockCount].request.query)
expect(variables).toEqual(mocks[mockCount].request.variables)
setMockCount(mockCount + 1)
setAttributes({
loading: true
})
process.nextTick(() => {
setAttributes(mocks[mockCount].result)
})
}
return [
verifyGraphQLMock,
attributes
]
})
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 15
MockedProvider is a real joke really, can’t count the time I lost debugging this crap
I am seeing the same problem with @apollo/client v3.3.20 when using
useLazyQuery
. Why this issue has come back given that it was already fixed?If you wanna mock using jest, you use the following approach
As you see, this approach even returns the mock function that is called in the code to be tested.
Your mocking seems to be incorrect, the above test succeeds for me after changing the result mock to
result: { data: { investment: { id: 'HOHO' } } }
See this comment
Here is an example of a component that uses
useLazyQuery
and a test that tests this component:Hey Guys! It solved when using useLazyQuery in MockedProvider!
I’m using @apollo/client ‘3.5.5’.
And the reason MockedProvider did not work on useLazyQuery was mismatching: ‘variables’, ‘data’. (+ When I used @apollo/client ‘3.3.21’, It does not work.)
In other words, (variables & data) of mocks should be same with (variables & data) of useLazyQuery in real component that you want to test.
For example,
&
So I recommend that using with type that declare Mock’s type. (To catch some mistake).
Like this,
I hope this would help.
I’m also having this problem. I cannot get respond data from ‘onCompleted’ in useLazyQuery(By MockedProvider). But I found a way mocking useLazyQuery of Apollo package.
You can make conditional return data(by switch or if statement) in function’s body. If you want to use respond data by ‘{ data }’(returned by useLazyQuery function), just use return value in second.
Looks like you are right! I see now, will have to take another look at my original implementation.
(Was expecting it to return what ever I set data to)
Thanks!