Use the React context API instead of mocking in unit tests

Does this meme show my age?

The Context API ⛅

Mocking with jest.spyOn 🕵️‍♀️

function MyComponent({ param }) {
const [data, setData] = useState(null);
// Fetch data on mount.
useEffect(() => {
fetch(`/data?param=${param}`)
.then(response => response.json())
.then(setData);
}, []);
// When data has not yet loaded, display a loading state.
if (data === null) {
return <strong>Loading...</strong>;
}
// When data has loaded, display it.
return <p>{JSON.stringify(data)}</p>;
}
function useData(param) {
const [data, setData] = useState(null);
// Fetch data on mount.
useEffect(() => {
fetch(`/data?param=${param}`)
.then(response => response.json())
.then(setData);
}, []);
return data;
}
function MyComponent({ param }) {
const data = useData(param);
// When data has not yet loaded, display a loading state.
if (data === null) {
return <strong>Loading...</strong>;
}
// When data has loaded, display it.
return <p>{JSON.stringify(data)}</p>;
}
jest.spyOn(useDataModule, 'default')
.mockReturnValue('my fake data here');

How can this all go wrong? 🤔

function useData(param) {
const { data } = useQuery(
'data',
async ({ pageParam }) => {
return (await fetch(`/data?param=${pageParam}`)).json();
},
);
return data;
}

What a pickle! 🥒

const MyApi = createContext(
async (param) => {
return (await fetch(`/data?param=${param}`)).json();
},
);
function useData(param) {
const callApi = useContext(MyApi);
const { data } = useQuery(
'data',
async ({ pageParam }) => {
return callApi(pageParam);
},
);
return data;
}
const TEST_API = jest.fn();function TestApiProvider({ children }) {
return (
<MyApi.Provider value={TEST_API}>
{children}
</MyApi.Provider>
);
}
renderHook(useData, {
initialProps: 'test-param',
wrapper: TestApiProvider,
});
expect(TEST_API).toHaveBeenCalledWith('/data?param=test-param');

Conclusion 🔚

Senior front end engineer / charlesstover.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store