Open kirankbs opened 6 years ago
@Jackman3005: The default behavior of the mock adapter is to return a 404 when a request can't be matched to a handler. The reason for this is that it's not possible to know whether the lack of a match was intentional or a mistake. You can change this to throw an exception when no match is found:
new MockAdapter(axiosInstance, { onNoMatch: "throwException" });
Could you check if that would work for you and if there's something we can still improve there?
Weirdly enough, this was the fix to my problem. Alll I had to do was to pass { onNoMatch: "throwException" }
to my mockAdapter initialization and the problem went away.
Today was the third time facing this issue. I don't even remember how i fixed it the previous times.
I was getting the same error Error: Request failed with status code 404
. I fixed making sure to declare the mocked request before actually rendering the component that makes the axios request.
Weirdly enough, this was the fix to my problem. Alll I had to do was to pass
{ onNoMatch: "throwException" }
to my mockAdapter initialization
This is really frustrating. I was convinced that it was throwing a 404 because the url was fake. Is it not possible to log that a request was made and no match was found? If there is a way to detect a no match, then there is a way to soft fail right?
Add more context here? https://github.com/ctimmerm/axios-mock-adapter/blob/master/src/handle_request.js#L131
Or have the default behaviour as throw an exception stating no match was found. Would it not be better to fail early and give a contextual error?
@djalmaaraujo I think its how you are using the base url. You can
console.log(mock.handlers.get)
to see if the right url is saved in the array.I just mocked this up and it works just fine isolated from Redux.
fit('it should work', () => { const SERVER_URL = '/test'; const requestInstance = axios.create({ baseURL: SERVER_URL, timeout: 2000, headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, }); const newMock = new MockAdapter(requestInstance); newMock.onGet('/api/quoteDetails/product/123456').reply(200, 'quoteDetailsData'); requestInstance.get('api/quoteDetails/product/123456') .then(response => console.log('response', response)) .catch(error => console.log('error', error)); });
Response console.log
response { status: 200, data: 'quoteDetailsData', headers: undefined, config: { adapter: null, transformRequest: { '0': [Function: transformRequest] }, transformResponse: { '0': [Function: transformResponse] }, timeout: 2000, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, validateStatus: [Function: validateStatus], headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, baseURL: '/test', method: 'get', url: '/api/quoteDetails/product/123456', data: undefined } }
yeah, the same using Redux, but why is it?
interesting thing is If I call loginRequest
, it won't work and say 404, but when I copy loginRequest
to Jest
it will work.
describe('when login', () => {
it('should return auth token if success',
async () => {
const username:string = "fz"
const role:string = 'host'
const password:string = "123456"
const user = {username,password,role}
mock.onPost(BASE_URL + "/login", {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": BASE_URL
}).reply(200, {'token':'123'})
// if calling loginRequest(), it won't work
axios.post("http://127.0.0.1:5000/login",
JSON.stringify(user),
{
headers:{
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": BASE_URL
}
})
expect(mock.history.post[0]["url"]).toEqual(BASE_URL + "/login");
// console.log(mock.history.post[0].url)
return
})
export function loginRequest(data:{username:string, password:string, role:string}) {
const d = JSON.stringify(data)
console.log(d)
return axios.post("http://127.0.0.1:5000/login",
d,
{
headers:{
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": BASE_URL
}
}
)
}
I was experiencing the same issue at my first try. I found out when use new MockAdapter(axios)
all your external endpoint would return 404 even you didn't declare. You can try this
const mocker = new MockAdapter(axios);
// Declare your mock
mocker.onGet('/user').reply(200, {});
// this must be the last line! it tell any endpoint doesn't match will let it pass through
mocker.onAny().passThrough();
Hope it help!
I haven't investigated too deeply yet, but axios-mock-adapter was working great for me on a very large project. After upgrading from webpack 4 to webpack 5 (with a few changes to babel for the polyfill changes), I suddenly started receiving 404's back in all of our unit tests. Almost everything else appears to be working, and the app still functions properly in a web browser.
Just closing the loop on my previous comment in case if helps someone else who stumbles into this thread. My issue was that karma-webpack needed a few more changes to work properly with webpack 5. This wasn't at all apparent because the only symptom was the 404's coming from axios-mock-adapter. I conditionally added the following lines to my webpack config for unit tests only and then everything started working again:
optimization: {
runtimeChunk: false,
splitChunks: false
},
Magic!
In my case the reasoning was pure fun & had nothing to do with axios-mock-adapter
. Leaving it here just in case it helps someone.
I use axios-retry
, so, when a request fails it retries it a couple of times. Great to have in prod, not so much in the testing environment.
I had axios-retry
configured in a service, so I had something like:
// ../services/http.ts
import axios from 'axios';
import axiosRetry from 'axios-retry';
const http = axios.create({
timeout: 1 * 1000 * 15,
});
axiosRetry(http, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay,
});
export default http;
Then, in tests I (sure) forgot about this fact & tried to use:
// some.test.ts
const httpMock = new MockAdapter(http);
// ...
httpMock
.onGet('...')
.replyOnce(500);
After the first 500
reply, axios-retry
retried the request the second time but (oops) we don't have any handler for this request registered anymore, so, the 404 error is issued.
I worked around that by mocking my http
module out with something like this:
// some.test.ts
import axios from 'axios';
jest.mock('../services/http', () => require('axios'));
const axiosMock = new MockAdapter(axios);
// ...
axiosMock
.onGet('...')
.replyOnce(500);
import axios, { AxiosRequestConfig } from 'axios';
import MockAdapter from "axios-mock-adapter";
const mock = new MockAdapter(axios);
// Update the endpoint to match the actual application endpoint
mock.onPost("http://localhost:3110/mockApi").reply(200, {
users: [{ id: 1, name: "John Smith" }],
});
const url = "http://localhost:3110/mockApi";
(async () => {
const config: AxiosRequestConfig<any> = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
data: {
'$mock': 'TEST_DATA'
}
}
try {
const response: any = await axios(url, config);
console.log("response->", response);
} catch (error) {
console.error("Error:", error);
}
})();
Proposed Solution:
I was able to intercept axios-mock-adapter onPost request
I don't know if it's the same issue or not but my mock requests also failed w/ 404 status and the problem for me was that the axios instance added default headers such as Content-Type
which I didn't check. I only checked my custom headers. So the solution for me was to change:
axiosMock
.onPost(`${SERVER_URL}/bla`, requestPayload, {
Authorization: AUTHORIZATION
});
To:
axiosMock
.onPost(`${SERVER_URL}/bla`, requestPayload, {
Authorization: AUTHORIZATION
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
});
Hope that helps.
pretty sure this happens with onPost
mock, and realy have no clue why it happens... I saw some comments on the internet say it's because of the headers, but i tried to match the headers, and it doesn't work for me.
I also did try change the call itself from post
to get
, and change the mock from onPost
to onGet
, and everything works flawlessly with the same headers... so really have no idea why the author wouldn't fix it for onPost
, or at least give some more meaningful error log...
Finally I do find a hacky workaround, just simply do it this way, and check your call's url and other stuff in the callback, and make sure it's the call u wanna test...
mockAdapter.onPost().reply(config => { if (config.url === 'your_url') { return [200, 'your response'] } });
i am using axios-mock-adapter to mock tests in react app. got below error while running single test but it is passing in case of all tests.
/home/dev/code/client/node_modules/react-scripts/scripts/test.js:22 throw err; ^ Error: Request failed with status code 404 at createErrorResponse (/home/dev/code/client/node_modules/axios-mock-adapter/src/utils.js:122:15) at Object.settle (/home/dev/code/client/node_modules/axios-mock-adapter/src/utils.js:102:16) at handleRequest (/home/dev/code/client/node_modules/axios-mock-adapter/src/handle_request.js:69:11) at /home/dev/code/client/node_modules/axios-mock-adapter/src/index.js:16:9 at MockAdapter. (/home/dev/code/client/node_modules/axios-mock-adapter/src/index.js:15:14)
at dispatchRequest (/home/dev/code/client/node_modules/axios/lib/core/dispatchRequest.js:52:10)