Open kirankbs opened 6 years ago
I can't do much with the little information that you're giving, but likely the code that adds the mock handlers does not get run when running a single test.
I got a similar error to @kirankbs.
My code seems to not evaluate the axios.get bit with mock
Here is a sample of my code
export const getLocationInfo = (lat, lng) => {
return ((dispatch) => {
return axios.get(process.env.API_LOCATION_URL+`/json?latlng=${lat},${lng}&key=${process.env.GOOGLE_KEY}`)
.then((response) => {
dispatch({ type: "FETCHED_LOCATION_INFO", payload: response.data.results });
}).catch((error) => {
dispatch({ type: 'FAILED_FETCHING_LOCATION_INFO', payload: error });
});
});
};
The test code below
it('should dispatch FETCHED_LOCATION_INFO when getLocationInfo completes successfully', (done) => {
let middlewares = [thunk];
let mockStore = configureMockStore(middlewares);
let store = mockStore({});
mock = new MockAdapter(axios);
mock.onGet('http://maps.google.com/').reply(200, {
data: {
results: [
{
formatted_address: 'Abc Rd, City, Country'
}
]
}
});
store.dispatch(getLocationInfo(-5.2177265, 12.9889)).then(() => {
const actualActions = store.getActions();
expect(expectedActions[0].type).toEqual(actualActions[0].type);
done();
});
});
This is my error
[ { type: 'FAILED_FETCHING_LOCATION_INFO',
payload: { Error: Request failed with status code 404
at createErrorResponse (/Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios-mock-adapter/src/utils.js:117:15)
at Object.settle (/Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios-mock-adapter/src/utils.js:97:16)
at handleRequest (/Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios-mock-adapter/src/handle_request.js:69:11)
at /Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios-mock-adapter/src/index.js:18:9
at new Promise (<anonymous>)
at MockAdapter.<anonymous> (/Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios-mock-adapter/src/index.js:17:14)
at dispatchRequest (/Users/brianhawi/Documents/learning-projects/weather-app/node_modules/axios/lib/core/dispatchRequest.js:52:10)
at <anonymous> config: [Object], response: [Object] } } ]
Getting the same error as mentioned above
mock = new MockAdapter(requestInstance)
mock.onPost(`${SERVER_URL}/api/cart`).reply(200, 'cart')
mock.onGet(`${SERVER_URL}/api/quoteDetails/product/`).reply(200, { data: {x: 2} })
@djalmaaraujo What does your http request look like for POST and GET?
@davidlewallen Not sure if I understood the question.
@djalmaaraujo can you show me the code that is making the request to ${SERVER_URL}/api/car
@davidlewallen
/**
* Axios Request Instance (Move to config later)
*/
export const requestInstance = axios.create({
baseURL: SERVER_URL,
timeout: 20000,
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }
})
/**
* Fetch QuoteDetails using ISBN
*/
export const buybackFetchQuoteDetails = (isbn) => {
return (dispatch) => {
if (!isbn) {
return dispatch({
type: 'BUYBACK/quoteDetailsFail',
payload: 'Invalid ISBN, please try another ISBN.'
})
}
dispatch({
type: 'BUYBACK/loading'
})
return createOrReturnCart().then((cart) => {
dispatch({
type: 'BUYBACK/createOrReturnCart',
payload: cart
})
return requestInstance.get(`api/quoteDetails/product/${isbn}`)
.then((response) => {
dispatch({
type: 'BUYBACK/quoteDetailsSuccess',
payload: response.data
})
})
.catch((error) => {
console.log('I ALWAYS GET CATCH HERE')
dispatch({
type: 'BUYBACK/quoteDetailsFail',
payload: (error.response.data && error.response.data.error) ? error.response.data.error : 'Invalid ISBN, please try another ISBN.'
})
return error
})
})
}
}
export const createOrReturnCart = () => {
return requestInstance.post('api/cart')
.then((response) => response.data)
.catch(err => err)
}
Spec:
describe('async quote details', () => {
let mock;
let dispatchMockSpy;
beforeEach(() => {
mock = new MockAdapter(requestInstance)
dispatchMockSpy = sinon.spy()
mock
.onPost(`${SERVER_URL}/api/cart`).reply(200, 'cart')
.onGet(`${SERVER_URL}/api/quoteDetails/product/123456`).reply(200, 'quoteDetailsData')
})
afterEach(() => {
mock.reset()
})
it("should dispatch data", () => {
const buybackFetchQuoteDetailsMock = buybackFetchQuoteDetails('123456')
buybackFetchQuoteDetailsMock(dispatchMockSpy).then((x) => {
expect(dispatchMockSpy.calledWith({
type: 'BUYBACK/loading'
})).toBeTruthy()
expect(dispatchMockSpy.calledWith({
type: 'BUYBACK/createOrReturnCart',
payload: 'cart'
})).toBeTruthy()
}).catch((x) => console.log(x))
})
})
@djalmaaraujo the code you link has no GET request to ${SERVER_URL}/api/cart
or a POST request to ${SERVER_URL}/api/quoteDetails/product/
@davidlewallen I updated the code above, please take a look. Just added what is requestInstance
. In the code above, the /api/cart works, but the get, does not.
@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 } }
@davidlewallen But why the /api/cart works and the other don't?
I just console.log requestInstance
● Console
console.log src/Actions/BuyBackActions.test.js:49
{ [Function: wrap]
request: [Function: wrap],
delete: [Function: wrap],
get: [Function: wrap],
head: [Function: wrap],
options: [Function: wrap],
post: [Function: wrap],
put: [Function: wrap],
patch: [Function: wrap],
defaults:
{ adapter: [Function: xhrAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 20000,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ common: [Object],
delete: {},
get: {},
head: {},
post: [Object],
put: [Object],
patch: [Object],
Accept: 'application/json',
'Content-Type': 'application/json' },
baseURL: 'http://localhost:8080/buyback' },
interceptors:
{ request: InterceptorManager { handlers: [] },
response: InterceptorManager { handlers: [] } } }
console.log src/Actions/BuyBackActions.js:46
@djalmaaraujo add console.log(JSON.stringify(mock.handlers, null, 2))
inside of your beforeEach
but after the mock calls and post that up
@davidlewallen
● Console
console.log src/Actions/BuyBackActions.test.js:59
{
"get": [
[
"http://localhost:8080/buyback/api/quoteDetails/product/123456",
null,
200,
"quoteDetailsData",
null
]
],
"post": [
[
"http://localhost:8080/buyback/api/cart",
null,
200,
"cart",
null
]
],
"head": [],
"delete": [],
"patch": [],
"put": []
}
I was using onAny, just fixed. see now
@davidlewallen The error returned in the catch
(in the src code), is this:
{ Error: Request failed with status code 404
at createErrorResponse (/Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios-mock-adapter/src/utils.js:110:15)
at Object.settle (/Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios-mock-adapter/src/utils.js:90:16)
at handleRequest (/Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios-mock-adapter/src/handle_request.js:55:11)
at /Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios-mock-adapter/src/index.js:16:9
at new Promise (<anonymous>)
at MockAdapter.<anonymous> (/Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios-mock-adapter/src/index.js:15:14)
at dispatchRequest (/Users/cooper/dev/valore/valore-buyback-webapp/client/node_modules/axios/lib/core/dispatchRequest.js:59:10)
at <anonymous>
config:
{ adapter: null,
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 20000,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ Accept: 'application/json',
'Content-Type': 'application/json' },
baseURL: 'http://localhost:8080/buyback',
method: 'get',
url: '/api/quoteDetails/product/123456',
data: undefined },
response:
{ status: 404,
config:
{ adapter: null,
transformRequest: [Object],
transformResponse: [Object],
timeout: 20000,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
baseURL: 'http://localhost:8080/buyback',
method: 'get',
url: '/api/quoteDetails/product/123456',
data: undefined },
data: undefined } }
@djalmaaraujo try removing the ${SERVER_URL}
and see if that helps?
@davidlewallen Same thing. Still have the /api/cart working, but not the other request. The difference is that this request is inside another promise. maybe that's the reason?
@djalmaaraujo hmm I am seeing something a little different on my end. Try adding this to createOrReturnCart
function:
const createOrReturnCart = () => requestInstance.post('/api/cart')
.then(response => response)
.catch((error) => {
console.log('error', error)
return error;
});
And see if you get an error there?
@davidlewallen I changed a little bit the code to show you the test results:
/**
* Fetch QuoteDetails using ISBN
*/
export const buybackFetchQuoteDetails = (isbn) => {
return (dispatch) => {
if (!isbn) {
return dispatch({
type: 'BUYBACK/quoteDetailsFail',
payload: 'Invalid ISBN, please try another ISBN.'
})
}
dispatch({
type: 'BUYBACK/loading'
})
return createOrReturnCart().then((cart) => {
console.log('CART PASSED')
dispatch({
type: 'BUYBACK/createOrReturnCart',
payload: cart
})
return requestInstance.get(`api/quoteDetails/product/${isbn}`)
.then((response) => {
console.log('QUOTE DETAILS RESOLVED')
dispatch({
type: 'BUYBACK/quoteDetailsSuccess',
payload: response.data
})
})
.catch((error) => {
console.log('ERROR IN QUOTE DETAILS')
dispatch({
type: 'BUYBACK/quoteDetailsFail',
payload: (error.response.data && error.response.data.error) ? error.response.data.error : 'Invalid ISBN, please try another ISBN.'
})
return error
})
})
}
}
const createOrReturnCart = () => requestInstance.post('/api/cart')
.then(response => response)
.catch((error) => {
console.log('error', error)
return error;
})
SPEC:
PASS src/Containers/BuyBackContainer/BuyBackContainer.test.js
PASS src/Actions/BuyBackActions.test.js
● Console
console.log src/Actions/BuyBackActions.js:32
CART PASSED
console.log src/Actions/BuyBackActions.js:47
ERROR IN QUOTE DETAILS
console.log src/Actions/BuyBackActions.test.js:81
{ Error: expect(received).toBeTruthy()
Expected value to be truthy, instead received
false
at buybackFetchQuoteDetailsMock.then.x (/Users/cooper/dev/valore/valore-buyback-webapp/client/src/Actions/BuyBackActions.test.js:75:11)
at <anonymous> matcherResult: { message: [Function], pass: false } }
Test Suites: 2 passed, 2 total
Tests: 6 passed, 6 total
Snapshots: 0 total
Time: 0.938s, estimated 1s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
@djalmaaraujo One last thing before I give up. Make these changes
mock
.onPost('/api/cart').reply(200, 'cart')
.onGet(/api\/quoteDetails\/product\/.+/).reply(200, 'quoteDetailsData')
See if that give any better results
@davidlewallen Sorry the delay, but still failing. I will give up, check for another alternative. Thanks for your time, honestly.
@davidlewallen I was able to make it work. I split the method into 2 methods and tested separately. I can't tell you exactly what is the issue, but I believe it's a bug from this mock-adapter, when you have a nested promise level, it's like the mock is not aware of that request.
@davidlewallen After another time facing the same issue, I think the solution is to pass (done) and wait for the correct ajax to finish.
Check this example, and it works:
it('should return cartItem data and dispatch BUYBACK/cartAddItem', (done) => {
mock
.onPost('/api/cart').reply(200, { id: 5 })
.onPost('/api/cart/addItem', {cartId: 5, isbn: 123456}).reply(200, expectedResponse)
buybackAddItemToCart(5, {productCode: '123456'}, dispatchMockSpy)
.then(() => {
expect(dispatchMockSpy.calledWith({
type: 'BUYBACK/cartLoading'
})).toBeTruthy()
expect(dispatchMockSpy.args[1][0].payload).toEqual({
cartItem: expectedResponse,
quoteDetails: { productCode: '123456' }
})
done()
})
.catch(err => {
done.fail('Should not call catch')
console.log(err)
})
})
In this case, I am always getting 404 for the /api/cart... but with the done, now it works.
Hi, Sorry for reviving the thread but because its still open it could make sense to reuse it as I'm facing the same issues described by @kirankbs, @HawiCaesar and @djalmaaraujo.
I'm not able to get it to work even with @djalmaaraujo's solution using the done
callback.
What could be missing here?
Dependencies: axios@0.15.3 axios-mock-adapter@1.15.0
The method under test:
export const createResource = field => {
return axios
.post(
"http://app.io/api/resource",
JSON.stringify({
field
})
);
};
The test:
it("should create a resource", () => {
const fieldValue = "field value",
resourceName = "resource name";
new MockAdapter(axios)
.onPost("http://app.io/api/resource", { field: fieldValue })
.reply(200, { field: fieldValue, name: resourceName});
return createResource(field).then(({ field, name }) => {
expect(field).toBe(fieldvalue);
expect(name).toBe(resourceName);
}).catch(error => {
console.error(error);
return error;
});
});
The error:
{ Error: Request failed with status code 404
at createErrorResponse (/home/pmgmendes/repo/node_modules/axios-mock-adapter/src/utils.js:117:15)
at Object.settle (/home/pmgmendes/repo/node_modules/axios-mock-adapter/src/utils.js:97:16)
at handleRequest (/home/pmgmendes/repo/node_modules/axios-mock-adapter/src/handle_request.js:73:11)
at /home/pmgmendes/repo/node_modules/axios-mock-adapter/src/index.js:18:9
at new Promise (<anonymous>)
at MockAdapter.<anonymous> (/home/pmgmendes/repo/node_modules/axios-mock-adapter/src/index.js:17:14)
at dispatchRequest (/home/pmgmendes/repo/node_modules/axios/lib/core/dispatchRequest.js:52:10)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:118:7)
config:
{ transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded' },
method: 'post',
url: 'http://app.io/api/resource',
data: '{"field":"field value"}'
},
response:
{ status: 404,
config:
{ transformRequest: [Object],
transformResponse: [Object],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'post',
url: 'http://app.io/api/resource',
data: '{"field":"field value"}'
},
data: undefined
}
}
+1
I'm using axios in a node service layer that utilizes axios.create
to put a common baseUrl
in all axios requests. The mock-adapter seems to failing to work in my case as well.
Getting exactly the same issue with a nested promise.
After debugging session focused on utils.js#findHandler()
I came to conclusion that the generated POST body didn't match the expected payload provided to the axios mock thus causing the 404.
The functions used within findHandler
method would benefit immensely by having some verbose logging. It would be much easier to understand what's the real reason behind a possible 404.
What version of node are people using? I am also facing the same issue and I believe I have chased it down to Utils.findHandler
.
My environment:
> process.versions
{ ...
node: '8.9.4',
v8: '6.1.534.50',
... }
To demonstrate the issue, go into your node_modules and update your utils.js
to the following:
function find(array, predicate) {
var length = array.length;
for (var i = 0; i < length; i++) {
var value = array[i];
const pred = predicate(value);
if (pred) return value;
else console.log(`Failed to match value: ${pred}`);
}
}
// ...
function isBodyOrParametersMatching(method, body, parameters, required) {
console.log('isBodyOrParametersMatching');
// ...
What you'll see is that the predicate fails to match with a log statement of:
Failed to match value: undefined
Further, you will not see isBodyOrParametersMatching
printed in the logs either.
My theory is that there is a bug in the way V8 handles [arbitrarily] complex bitwise statements. I've seen this behavior (where it returns undefined instead of a boolean) in another of our internal projects (completely unrelated to axios-mock-adapter
).
Once you confirmed the behavior above, try replacing the findHandler
method with the following:
function findHandler(handlers, method, url, body, parameters, headers, baseURL) {
console.log(arguments);
console.log(handlers);
return find(handlers[method.toLowerCase()], function(handler) {
let urlMatch = false;
if (typeof handler[0] === 'string') {
urlMatch = isUrlMatching(url, handler[0]) || isUrlMatching(combineUrls(baseURL, url), handler[0]);
} else if (handler[0] instanceof RegExp) {
urlMatch = handler[0].test(url) || handler[0].test(combineUrls(baseURL, url));
}
const bodyParamMatch = urlMatch && isBodyOrParametersMatching(method, body, parameters, handler[1]);
const headersMatch = bodyParamMatch && isRequestHeadersMatching(headers, handler[2]);
return headersMatch
});
}
You'll notice that isBodyOrParametersMatching
is printed in the logs as expected and the predicate matches successfully.
My theory is that there is a bug in the way the V8 runtime parse boolean statements. Specifically, when the V8 runtime parses a bitwise boolean statement where there is a parentheses group followed by a method invocation. For whatever reason, I believe V8 falls on its face and returns undefined
where that value should otherwise be unattainable.
As I said earlier, I've seen this in an internal ReactJS app (which was not using axios) running in the latest Chrome browser. I'll see if I can put together a sample app to test my theory.
I'll also put together a PR to solve this issue (with the updated findHandler
method). Though it will have to wait until I get home tonight as we are unable to push anything to github from our office 😢
PS.- If someone else wants to take the code above and create a PR before I do, please feel free. (Just make sure to reference this issue)
Note: An issue has been opened within V8 https://bugs.chromium.org/p/v8/issues/detail?id=7949
I get the 404 randomly! If I chain three onGet
methods it works, next time I get 404 then unchain the methods and it works. Repat to infinite.
I'm lost. It is as it were working when HMR but not working on refresh (I am working with storybook btw)
See this video http://recordit.co/Hj45OY8yjB
I'm facing the same error when using onPost.
I had this problem in my tests and solved it creating just one instance of the mock object: export const mock = new MockAdapter(axios);
and then just import { mock } from "../../utils/mockAdapter";
For anyone who is still stuck in this,
I had same problem, i was passing data to mock.onPost()
, just remove the data part.. it should work fine
mock.onPost('http://localhost:8000/auth', {data: someData})
.reply(200);
to
mock.onPost('http://localhost:8000/auth')
.reply(200);
@s8sachin , what do you do if you need to a assert certain data was returned?
@sagaban , you're suggestion has worked perfectly. Just remember to run the mock.reset() in your afterEach. Thank you.
@gkohen , passing data didn't matter in my case since i'm writing mock.onPost().reply()
on each of test cases... so that each of them have different replies based on that particular test case... I guess sending data doesn't matter since we send required reply no matter what.
and, does using @sagaban 's answer, is is possible to send data and not receive 404 ?
I had this problem in my tests and solved it creating just one instance of the mock object:
export const mock = new MockAdapter(axios);
and then justimport { mock } from "../../utils/mockAdapter";
This throws an obvious error for me that mock
has already been declared. What am I not understanding?
Here's my code:
const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')
let mock = new MockAdapter(axios)
const { mock } = require( "../../utils/mockAdapter")
const { mock } = require( "../../utils/mockAdapter")
^
SyntaxError: Identifier 'mock' has already been declared
I had this problem in my tests and solved it creating just one instance of the mock object:
export const mock = new MockAdapter(axios);
and then justimport { mock } from "../../utils/mockAdapter";
This throws an obvious error for me that
mock
has already been declared. What am I not understanding?Here's my code:
const axios = require('axios') const MockAdapter = require('axios-mock-adapter') let mock = new MockAdapter(axios) const { mock } = require( "../../utils/mockAdapter")
const { mock } = require( "../../utils/mockAdapter") ^ SyntaxError: Identifier 'mock' has already been declared
First of all: I don't know if my approach is correct. That being said: you have to initialize and export the
mock
instance in theutils/mockAdapter.js
file and then import that instance in the file where you want to use it. e.g.// tests/unit/utils/mockAdapter.js import Vue from "vue"; import VueAxios from "vue-axios"; import MockAdapter from "axios-mock-adapter"; import axios from "axios";
Vue.use(VueAxios, axios);
export const mock = new MockAdapter(axios);
and
``` js
//tests/unit/store/actions.spec.js
import { mock } from "../utils/mockAdapter";
Hi all!
Is there any news on this issue? I'm facing the same problem.
Thank you all!
I had this problem in my tests, if don't pass data like @s8sachin ,it can be work
I had same issues and by having mockAdapter in a single instance file and then import it in all other mock files did the trick .
so create a file mocks/mockInstance.js
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
export default new MockAdapter(axios);
then use it like this :
import mock from 'mocks/mockInstance';
mock.onGet(getRolesURI).reply(200, {
roles: fakeRolesTable,
});
Fix this issue by making sure the mocked payload was identical to the payload used to make the actual call. Attention to details my friends 😄
Which coincidentally makes sense since axios matches a request by its URL and Payload. If a URL is the same but the payload is different then its a different request. Also if you have two requests with the same URL and Payload then technically the response should be the same.
I'm either blind, dumb, or both. This looks to match exactly, but doesn't work. Same case I always seem to have with axios-mock-adapter for quite some time now. https://stackoverflow.com/questions/54638466/axios-mock-adapter-not-matching-url-as-expected
in my case running npm test
instead of npm run test
and replacing the URL with the correct value in an env variable used in the code.
Hi! I have same issue - I have two tests in describe block and each of them runs perfectly, but running both of them leads to fail. My current approach is:
_axiosMockAdapter.js:
import Vue from "vue";
import VueAxios from "vue-axios";
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
Vue.use(VueAxios, axios);
export default new MockAdapter(axios);
test.js:
import mockAxios from './_axiosMockAdapter'
import axios from 'axios';
import global from '../global';
describe('accessing to server', () => {
it('sends data on "Save" to predefined url', async done => {
const wrapper = mount(global);
const url = wrapper.vm.$data.url;
const saveButton = wrapper.find({ref: 'save'});
const fakeData = {...some data...}
wrapper.vm.$nextTick(() => {
saveButton.trigger('click');
expect(spyAxiosOnPut).toHaveBeenCalledWith(url, {...fakeData});
const spyAxiosOnPut = jest.spyOn(axios, 'put');
spyAxiosOnPut.mockClear();
done();
});
})
it('fetches data from predefined url when created', async done => {
const flushPromises = () => new Promise(resolve => setTimeout(resolve))
const wrapper = mount(global);
const url = wrapper.vm.$data.url;
const fakeData = {...some data...}
mockAxios.onGet(url).reply(200, fakeData);
await flushPromises();
wrapper.vm.$nextTick(() => {
expect(mockAxios.history.get[0].url).toEqual(url);
expect(wrapper.vm.$data.data).toEqual(fakeData);
done();
})
})
})
Actually, it seems to me i tried all of the methods in this discussion - i used axios strictly from package, i imported it from other file (now i use this method), I tried to reset it on each iteration - didn't help either:
describe('accessing to server', () => {
let mockAxios;
beforeAll(() => {
mockAxios = new MockAdapter(axios)
});
afterEach(() => {
mockAxios.reset()
});
afterAll(() => {
mockAxios.restore()
});
....
Even run yarn test
and yarn run test
What am I doing wrong? I am using rails webpacker - not quite sure if it makes sense for current issue. All other non-mocking-axios tests are passing fine, problem is in running multiple mocking-axios tests.
Aside from only exporting one mock instance, I've also been bitten in the butt when I use the spread operator in the body and the object contains extra fields than expected. Just wanted to share.
I really wish we'd see some error a la: Expected mock adapter to have PATH be requested with BODY_A, but was requested with BODY_B.
I'm having the same error.
I tried the following:
adapter.onPost(`${baseUrl}/endpoint`).reply(config => {
console.log('config', config);
return [200];
});
This return the 404 error: Error: Request failed with status code 404
But dropping the url matcher works:
adapter.onPost().reply(config => {
console.log('config', config);
return [200];
});
Note that config.url
matches the value of `${baseUrl}/endpoint`
I faced the same error and the solution from @vsakaria worked for me. Basically the payload wasn't matching that's why it will also work if you remove the payload from mock.onPost()
like @s8sachin mentioned.
I spent awhile on a bug today where we had accidentally passed in incorrect data in an onPost
body and were receiving a 404 when our app code tried to make the call with the correct data... I found that the 404 was a difficult message to work with. Because this particular test had multiple API calls, I couldn't sort out which one it was immediately, and I had to fiddle with things until I noticed my mistake. In fact... I ended up console.log
ging every parameter to the utils.createAxiosError
function and that's where I found our mistake...
Is there anyway that we could get more output for this situation? Like "Hi you sent me this payload, header, url, etc but that doesn't match anything you've set up for me." If being extra ambitious, we could show them the closes matches to the config MockAdapter received. I'd be happy to help with this, but I just naively felt like I want to put console logs in the utils.createAxiosError
block, which clearly can't be the best approach (also noticing the toJSON() function definition there, how do you expect that to be used?)
Here is a code sample that illustrates the situation:
Test Setup Code
import axios from 'axios'
const mockAdapter = new MockAdapter(axios)
mockAdapter.onPost('/api/my-url', {
something: [
{
i: "hope",
that: "this",
matches: "whoops-typo"
}
]
}).replyOnce(200)
App Code
await axios
.post('/api/my-url/', {
something: [
{
i: "hope",
that: "this",
matches: "but-it-wont"
}
]
})
Resulting Message
Error: Request failed with status code 404
at createAxiosError (/Users/hello/some-project/node_modules/axios-mock-adapter/src/utils.js:148:15)
at Object.settle (/Users/hello/some-project/node_modules/axios-mock-adapter/src/utils.js:127:11)
at handleRequest (/Users/hello/some-project/node_modules/axios-mock-adapter/src/handle_request.js:126:15)
at /Users/hello/some-project/node_modules/axios-mock-adapter/src/index.js:26:9
at new Promise (<anonymous>)
at MockAdapter.<anonymous> (/Users/hello/some-project/node_modules/axios-mock-adapter/src/index.js:25:14)
at dispatchRequest (/Users/hello/some-project/node_modules/axios/lib/core/dispatchRequest.js:59:10)
Potential Desired Message
Error: Request did not match any stubbed request and pass-through mode is turned off!
...
at myAppMethod (/Users/..../myAppAxiosCall.js:44)
...
The un-matched request: {
method: 'POST',
url: '/api/my-url',
body: {
something: [
{
i: "hope",
that: "this",
matches: "but-it-wont"
},
]
},
headers: ...
Thank you for reading this far. I apologize if this is not the thread to have posted this request. I am happy to make a new issue. Again, I would consider helping out if I had the guidance for what you would prefer.
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)