Videos
I have design of a dashboard and and i wanna create a simple dummy api which contains all these data which are being shown in this dashboard and and there line chart in that dashboard which needs to be interactive with data of that dummy api
Hello, I'm starting to develop a web application using React as my frontend, I'm also coding the backend API using Django.
I was wondering what is the recommended method to create a mock API calls in React so I can focus on my frontend first without having to constantly update my backend API.
Also, It would be nice if I could set some sort of variable toggle so I can quickly switch between using the real backend API and the mock API.
I'm using Axios to make my API calls.
Any suggestions?
Thanks!
By default jest.mock calls are hoisted by babel-jest...
...this means they run before anything else in your test file, so any variables declared in the test file won't be in scope yet.
That is why the module factory passed to jest.mock can't reference anything outside itself.
One option is to move the data inside the module factory like this:
jest.mock("../utils/userUtils", () => {
const users = [ /* mock users data */ ];
return {
getUsers: jest.fn(() => Promise.resolve(users))
};
});
jest.mock("../utils/roleUtils", () => {
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
return {
getRolesWithUsers: jest.fn(() => Promise.resolve(usersWithRoles)),
getRoles: jest.fn(() => Promise.resolve(roles))
};
});
Another option is to mock the functions using jest.spyOn:
import * as userUtils from '../utils/userUtils';
import * as roleUtils from '../utils/roleUtils';
const users = [ /* mock users data */ ];
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
const mockGetUsers = jest.spyOn(userUtils, 'getUsers');
mockGetUsers.mockResolvedValue(users);
const mockGetRolesWithUsers = jest.spyOn(roleUtils, 'getRolesWithUsers');
mockGetRolesWithUsers.mockResolvedValue(usersWithRoles);
const mockGetRoles = jest.spyOn(roleUtils, 'getRoles');
mockGetRoles.mockResolvedValue(roles);
And another option is to auto-mock the modules:
import * as userUtils from '../utils/userUtils';
import * as roleUtils from '../utils/roleUtils';
jest.mock('../utils/userUtils');
jest.mock('../utils/roleUtils');
const users = [ /* mock users data */ ];
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
userUtils.getUsers.mockResolvedValue(users);
roleUtils.getRolesWithUsers.mockResolvedValue(usersWithRoles);
roleUtils.getRoles.mockResolvedValue(roles);
...and add the mocked response to the empty mock functions.
Don't mock the tool making API calls; stub the server responses. Here's how I would re-write your test using an HTTP interceptor called nock.
import "jest-dom/extend-expect";
import React from "react";
import { render, waitFor } from "react-testing-library";
import UserTable from "../UserTable";
const users = [
{
name: "Benglish",
iden: "63fea823365f1c81fad234abdf5a1f43",
roles: ["eaac4d45c3c41f449cf7c94622afacbc"]
}
];
const roles = [
{
iden: "b70e1fa11ae089b74731a628f2a9b126",
name: "senior dev"
},
{
iden: "eaac4d45c3c41f449cf7c94622afacbc",
name: "dev"
}
];
const usersWithRoles = [
{
name: "Benglish",
iden: "63fea823365f1c81fad234abdf5a1f43",
roles: [
{
iden: "eaac4d45c3c41f449cf7c94622afacbc",
name: "dev"
}
]
}
];
describe("<UserTable/>", () => {
it("shows users", async () => { // <-- Async to let nock kick over resolved promise
nock(`${server}`)
.get('/users')
.reply(200, {
data: users
})
.get('/usersWithRoles')
.reply(200, {
data: usersWithRoles
})
.get('/roles')
.reply(200, {
data: roles
});
const { queryByText } = render(<UserTable />);
await waitFor(() => expect(queryByText("Billy")).toBeTruthy()); // <-- Is this supposed to be "Benglish"?
});
});
Now your test suite is unaware of how you get the data, and you don't have to maintain complicated mocks. Check out a blog post I wrote Testing Components that make API calls for a deeper dive.