Testing with Jest on components with RTK-query doesn't catch errors
I'm currently writing tests in jest and testing-library, while using msw to mock my results as well as errors. On a browser, it catches errors fine, and returns the results fine as well.
When mocking endpoints with msw on jest, it properly returns the data I'm trying to mock. However, my lazy query's result of error, isError, isSuccess, are all false, while isUnitialized is true. When I'm trying to see if it's properly catching the error, it fails to catch the error.
I have a component here where if one of the endpoint returns an error, I display a snackbar with an error message. However, It never reaches the catch exception.
Part of my code I'm trying to test
const [fetchBuildingsUsage, { error, isError, isSuccess, isUninitialized }] =
useLazyGetBuildingsUsageQuery();
const [getOverallUsage] = useLazyGetOverallUsageQuery();
const fetchAllRelevantData = useCallback(
async (payload: RelevantDataPayload) => {
const { from_date, to_date, ...rest } = payload;
const dashboardPayload: Partial<DashboardProps> = {
from: from_date,
to: to_date,
...rest
};
try {
const buildings: BuildingUsageProps[] = await fetchBuildingsUsage(
{
from_date: payload.from_date,
to_date: payload.to_date
},
true
).unwrap();
console.log({ buildings, error, isError, isSuccess, isUninitialized });
// when i stub the response as 400 error on my test with msw:
// buildings = undefined
// error = undefined
// isError = false
// isSuccess = false
// isUninitialized = true
} catch (err) {
// no matter what, it never reaches here.
console.log({ err });
return;
}
.....
My Test:
const server = setupServer(rest.get('*/overall_usage', (req, res, ctx) => {
return res(ctx.status(200), ctx.json(overallBuilding));
}),
rest.get('*/buildings/usage', (req, res, ctx) => {
return res(ctx.status(200), ctx.json({ buildings }));
}));
beforeAll(() => server.listen());
afterEach(() => {
server.restoreHandlers();
store.dispatch(dashboardApi.util.resetApiState());
store.dispatch({ type: 'reset' });
});
afterAll(() => {
server.resetHandlers();
server.close();
});
test('DatePicker - fetch buildings usage error response displays proper message and doesnt activate buttons', async () => {
render(
<>
<AlertSnackbar />
<DatePicker />
</>
);
await user.click(screen.getByText('1D'));
expect(
await screen.findByText(
'Something went wrong obtaining building data. Please refresh and try again'
)
);
});
In my render function, I'm properly rendering all the providers including the redux provider.
When i stub response data, it goes through my rtk-query endpoint's transformResponse, as I can see the console.log in my terminal (but isUninitialized is still true). When I set it up to return status 400 through msw, it doesnt catch the error, instead returns undefined as a result, but isError, isSuccess are both false, while it DOESN'T go through transformResponse.
server.use(
rest.get('*/buildings/usage', (req, res, ctx) => {
return res(
ctx.status(400),
ctx.json({
data: {
code: 'fail',
errors: [{ error: 'Error fetching buildings usage' }]
},
status: 400
})
);
})
);
It seems like intercepting results through node doesn't work well with rtk-query. Anyone running into the same issue? I've tried just about everything, including chaining .then and .catch after unwrap().
To Summarize the issue:
- Stubbing success response for lazy query returns proper response, but isSuccess is false, and isUninitialized is false. It triggers transformResponse properly.
- Stubbing error response for lazy query doesn't return proper error response, doesnt trigger catch exception, instead returns undefined as if the response was successful but it returned undefined, but isError and isSuccess is false, and isUnitialized is true. It does NOT trigger transformResponse.
- When testing it in the browser, it works properly and catches error properly as well.
Anyone try writing component tests for rtk-query and experience the same issue when testing for error cases? If it worked for you, let me know, and I'll go ahead and close this issue. I just haven't seen anything online regarding this.
Can you put together a CodeSandbox or repo that reproduces the issue? You could also use Replay ( https://replay.io/record-bugs ) to record this and share the recording link publicly with us.
@markerikson https://github.com/ymoon715/rtk-query-msw
Here's an example. After thorough testing, it seems that it might be an issue with msw's resetHandlers() method. Let me know what you think.
I also created an issue on msw's github, since I think this may be a bug on their end. https://github.com/mswjs/msw/issues/1377