mocking the apollo hook
jest.mock("@apollo/client", () => ({
...jest.requireActual("@apollo/client"),
useApolloClient: () => ({
query: jest.fn().mockResolvedValueOnce({
data: { myReturnValue: { some: "data" } },
loading: false,
errors: undefined,
}),
}),
}))
my function
const myFunction = (input) => {
console.log("called this?") // this 100% gets called in the test
const data = { ...defaultData, ...input }
return client
.query({
query: Query,
fetchPolicy: "network-only",
variables: {},
})
.then(({ data, errors }) => {
if (!data?) {
alert(errors)
} else {
console.log("in else block") // this 100% gets called in the test
runFunction()
}
})
}
in my test it is logging: "in else block"
and in my test I have:
fireEvent.click(screen.getByText("My Button Text"))
await waitFor(() => expect(useApolloClient().query).toBeCalledTimes(1))
In the test output I get
Expected number of calls: 1
Received number of calls: 0
why is this? It definitely called client.query
as it got in the logs
As @phry said, don't mock @apollo/client
module. Instead, follow the Testing React components guide.
Standing from the perspective of the user to test the component, which is equivalent to the black box test. Do not test the specific implementation(such as expect(someMethod).toBeCalled()
). Instead, we should assert what the component renders. After the user interacts with the component, what changes the rendering content will be
e.g.
index.tsx
:
import React, { useState } from 'react';
import { gql, useApolloClient } from '@apollo/client';
export const GET_DOG_QUERY = gql`
query GetDog($name: String) {
dog(name: $name) {
id
name
breed
}
}
`;
export function SomeComponent() {
const client = useApolloClient();
const [data, setData] = useState();
console.log("🚀 ~ SomeComponent ~ data:", data)
const onClick = () => {
client
.query({
query: GET_DOG_QUERY,
fetchPolicy: 'network-only',
variables: {
name: 'Buck',
},
})
.then(({ data, errors }) => {
setData(data);
});
};
return (
<div>
<button onClick={onClick}>My Button Text</button>
{data && <span>{data.dog.breed}</span>}
</div>
);
}
index.test.tsx
:
import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { GET_DOG_QUERY, SomeComponent } from '.';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
describe('78333569', () => {
test('should pass', async () => {
const mocks = [
{
request: {
query: GET_DOG_QUERY,
variables: {
name: 'Buck',
},
},
result: {
data: {
dog: { id: '1', name: 'Buck', breed: 'bulldog' },
},
},
},
];
render(
<MockedProvider mocks={mocks} addTypename={false}>
<SomeComponent />
</MockedProvider>,
);
fireEvent.click(screen.getByText('My Button Text'));
expect(await screen.findByText('bulldog')).toBeInTheDocument();
});
});
Test result:
console.log
🚀 ~ SomeComponent ~ data: undefined
at log (stackoverflow/78333569/index.tsx:18:11)
console.log
🚀 ~ SomeComponent ~ data: { dog: { id: '1', name: 'Buck', breed: 'bulldog' } }
at log (stackoverflow/78333569/index.tsx:18:11)
PASS stackoverflow/78333569/index.test.tsx
78333569
√ should pass (78 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.332 s, estimated 3 s
Ran all test suites related to changed files.
package versions:
"@apollo/client": "^3.9.11"