I use axios-mock-adapter
to mock my API, it works correctly but on one mock it returns a 404 error and I cannot found why.
There is here the sandbox with test, you can see when we run the test, the second check failed because the axios POST
call haven't be mock. I have try to remove the header part but the sandbox has just crash when I have run test.
import axios from "axios";
import MockAdapter from 'axios-mock-adapter';
import Utils from "../Utils/Utils";
// Global variable for post request with axios
global.users_post = axios.create({
baseURL: "http://localhost:5000/api/",
headers: {'Content-Type': 'application/json'}
});
/* Mockup API */
var userMock = new MockAdapter(users_post);
const user_resp_full = {
data: {
first_name: "Test",
last_name: "Test",
email: "[email protected]",
address: "Test",
zipcode: 1010,
city: "Test",
admin: false
}
}
const testAPI = () => {
userMock
.onPost("users", user_resp_full, Utils.getAuth())
.reply(200, {data: {status: "success"}});
}
test("something", async () => {
let tree = shallow(<UserManage type="create" uuid="" />);
testAPI();
await flushPromises();
// Some test
tree.find("#confirm-create").simulate("click");
await flushPromises();
// Error 404, mock isn't trigger
})
I have already check, data is the same, same for endpoint but it seems doesn't mock it correctly.
function (fields) {
users_post.post("users", fields, Utils.getAuth())
.then(resp => {
let data = resp.data;
// Do something
})
.catch(resp => {
let data = resp.response.data;
// Display error
});
}
At this point, in my Jest test it returns a 404 error, so it hasn't mock my endpoint API (Other works).
The Utils.getAuth()
function returns a header with a auth token.
That concerns content of data send (First is before the test call with mock, second is in the tested function and data log is the data send to api):
console.log src/tests/UserManage.test.js:222
POST USER 2
{"first_name":"Test","last_name":"Test","email":"[email protected]","address":"Test","zipcode":1010,"city":"Test","admin":false}
console.log src/Components/Users/UserManage.js:152
POST USER
console.log src/Components/Users/UserManage.js:153
{"first_name":"Test","last_name":"Test","email":"[email protected]","address":"Test","zipcode":1010,"city":"Test","admin":false}
This error happen only when I use a POST
request with a header like that:
axios.post("http://localhost/api/user/update", {name: "Test"}, {headers: {"Authorization": "Bearer token")}});
I have see on axios-mock-adapter github test page that eventually we should put headers
in test without the label before:{headers: {Autorization: "Bearer token"}}
become {Autorization: "Bearer token"}
But unfortunately it doesn't work better than I have.
With the response of Matt Carlotta and his codesandbox, I modify mine with 2 examples of fixed issue:
POST
request mock using axios*POST
request mock using an instance of axios** With axios-mock-adapter
404 means The server has not found anything matching the Request-URI. If you put in the wrong URI or bad URI that is your problem and the reason you didn't get to a resource whether a HTML page or IMG.
Based on the code above, is it correct to return a NOT_FOUND status ( 404 ), or should I be returning 204 , or some other more appropriate code? If you would expect a resource to be there, because it is looked up using an ID, then a 404 is expected. Something goes wrong, the resource you need to be there is not found.
Axios Mock Adapter Instance — This is used to define the Mock request handling code to define the Mock data. Axios Mock Instance — This is used within React to invoke the API as a typical Axios instance.
Okay, this was a tricky one. The issue is on the axios-mock-adapter package. It requires an instance of axios using the .create()
method.
See here:
creating an instance
In your App.js, use:
import axios from "axios";
const instance = axios.create();
instance.post("http://localhost/api/user/update", {name: "Test"}, {headers: {"Authorization": "Bearer token")}});
Nothing needs to be changed in the tests though.
I got the hint from tests of axios-mock-adapter.
An example of such is: post test
Alrighty, round two.
flushPromises
function isn't resolving promises
properly when that promise
takes some time to respond. The workaround is to return
the promise
and stick an await
in front of it within the .test.js
file. Since we're using await
on the promise
, await flushPromises()
isn't needed.headers
within the onPost
mocked function will cause the function to throw an error. Since you're just mocking this request (and not actually testing its integration), you don't need to include them. However, since you're already using a custom axios
configuration anyway, you can just include the headers
in the axiosConfig.js
file. See the working example of your codesandbox for more information.As demonstrated in the Unit Testing
codesandbox below, if you try to use await flushPromises()
on the deleteUserDataOverTime
method, it fails. It fails because it didn't resolve the promise
. This promise
takes some time to resolve and isn't being handled properly.
In addition, due to the asynchronous
nature of the tests, you shouldn't include unit
and integration
tests within the same test file. Since the tests are asynchronous
, calling mockAxios.reset()
or mockAxios.restore()
on the same mocked request or same mocked instance -- to make any additional real or fake API calls -- can and will inadvertently impact all the API calls (again they're asynchronous, not synchronous tests).
Working example of Unit testing an API: https://codesandbox.io/s/6z36z6pzyr (fake API -- includes GET
, PUT
, POST
and DELETE
)
Working example of Integration testing an API: https://codesandbox.io/s/7z93xnm206 (real API -- only includes GET
, but functionality should remain the same for PUT
, POST
, and DELETE
)
Working example of your codesandbox: https://codesandbox.io/s/526pj28n1n
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With