Code Monkey home page Code Monkey logo

axios-mock-adapter's Introduction

axios-mock-adapter

Axios adapter that allows to easily mock requests

Installation

Using npm:

$ npm install axios-mock-adapter --save-dev

It's also available as a UMD build:

axios-mock-adapter works on Node as well as in a browser, it works with axios v0.17.0 and above.

Example

Mocking a GET request

var axios = require("axios");
var MockAdapter = require("axios-mock-adapter");

// This sets the mock adapter on the default instance
var mock = new MockAdapter(axios);

// Mock any GET request to /users
// arguments for reply are (status, data, headers)
mock.onGet("/users").reply(200, {
  users: [{ id: 1, name: "John Smith" }],
});

axios.get("/users").then(function (response) {
  console.log(response.data);
});

Mocking a GET request with specific parameters

var axios = require("axios");
var MockAdapter = require("axios-mock-adapter");

// This sets the mock adapter on the default instance
var mock = new MockAdapter(axios);

// Mock GET request to /users when param `searchText` is 'John'
// arguments for reply are (status, data, headers)
mock.onGet("/users", { params: { searchText: "John" } }).reply(200, {
  users: [{ id: 1, name: "John Smith" }],
});

axios
  .get("/users", { params: { searchText: "John" } })
  .then(function (response) {
    console.log(response.data);
  });

When using params, you must match all key/value pairs passed to that option.

To add a delay to responses, specify a delay amount (in milliseconds) when instantiating the adapter

// All requests using this instance will have a 2 seconds delay:
var mock = new MockAdapter(axiosInstance, { delayResponse: 2000 });

You can restore the original adapter (which will remove the mocking behavior)

mock.restore();

You can also reset the registered mock handlers with resetHandlers

mock.resetHandlers();

You can reset both registered mock handlers and history items with reset

mock.reset();

reset is different from restore in that restore removes the mocking from the axios instance completely, whereas reset only removes all mock handlers that were added with onGet, onPost, etc. but leaves the mocking in place.

Mock a low level network error

// Returns a failed promise with Error('Network Error');
mock.onGet("/users").networkError();

// networkErrorOnce can be used to mock a network error only once
mock.onGet("/users").networkErrorOnce();

Mock a network timeout

// Returns a failed promise with Error with code set to 'ECONNABORTED'
mock.onGet("/users").timeout();

// timeoutOnce can be used to mock a timeout only once
mock.onGet("/users").timeoutOnce();

Passing a function to reply

mock.onGet("/users").reply(function (config) {
  // `config` is the axios config and contains things like the url

  // return an array in the form of [status, data, headers]
  return [
    200,
    {
      users: [{ id: 1, name: "John Smith" }],
    },
  ];
});

Passing a function to reply that returns an axios request, essentially mocking a redirect

mock.onPost("/foo").reply(function (config) {
  return axios.get("/bar");
});

Using a regex

mock.onGet(/\/users\/\d+/).reply(function (config) {
  // the actual id can be grabbed from config.url

  return [200, {}];
});

Using variables in regex

const usersUri = "/users";
const url = new RegExp(`${usersUri}/*`);

mock.onGet(url).reply(200, users);

Specify no path to match by verb alone

// Reject all POST requests with HTTP 500
mock.onPost().reply(500);

Chaining is also supported

mock.onGet("/users").reply(200, users).onGet("/posts").reply(200, posts);

.replyOnce() can be used to let the mock only reply once

mock
  .onGet("/users")
  .replyOnce(200, users) // After the first request to /users, this handler is removed
  .onGet("/users")
  .replyOnce(500); // The second request to /users will have status code 500
// Any following request would return a 404 since there are
// no matching handlers left

Mocking any request to a given url

// mocks GET, POST, ... requests to /foo
mock.onAny("/foo").reply(200);

.onAny can be useful when you want to test for a specific order of requests

// Expected order of requests:
const responses = [
  ["GET", "/foo", 200, { foo: "bar" }],
  ["POST", "/bar", 200],
  ["PUT", "/baz", 200],
];

// Match ALL requests
mock.onAny().reply((config) => {
  const [method, url, ...response] = responses.shift();
  if (config.url === url && config.method.toUpperCase() === method)
    return response;
  // Unexpected request, error out
  return [500, {}];
});

Requests that do not map to a mock handler are rejected with a HTTP 404 response. Since handlers are matched in order, a final onAny() can be used to change the default behaviour

// Mock GET requests to /foo, reject all others with HTTP 500
mock.onGet("/foo").reply(200).onAny().reply(500);

Mocking a request with a specific request body/data

mock.onPut("/product", { id: 4, name: "foo" }).reply(204);

Using an asymmetric matcher, for example Jest matchers

mock
  .onPost(
    "/product",
    { id: 1 },
    expect.objectContaining({
      Authorization: expect.stringMatching(/^Basic /),
    })
  )
  .reply(204);

Using a custom asymmetric matcher (any object that has a asymmetricMatch property)

mock
  .onPost("/product", {
    asymmetricMatch: function (actual) {
      return ["computer", "phone"].includes(actual["type"]);
    },
  })
  .reply(204);

.passThrough() forwards the matched request over network

// Mock POST requests to /api with HTTP 201, but forward
// GET requests to server
mock
  .onPost(/^\/api/)
  .reply(201)
  .onGet(/^\/api/)
  .passThrough();

Recall that the order of handlers is significant

// Mock specific requests, but let unmatched ones through
mock
  .onGet("/foo")
  .reply(200)
  .onPut("/bar", { xyz: "abc" })
  .reply(204)
  .onAny()
  .passThrough();

Note that passThrough requests are not subject to delaying by delayResponse.

If you set onNoMatch option to passthrough all requests would be forwarded over network by default

// Mock all requests to /foo with HTTP 200, but forward
// any others requests to server
var mock = new MockAdapter(axiosInstance, { onNoMatch: "passthrough" });

mock.onAny("/foo").reply(200);

Using onNoMatch option with throwException to throw an exception when a request is made without match any handler. It's helpful to debug your test mocks.

var mock = new MockAdapter(axiosInstance, { onNoMatch: "throwException" });

mock.onAny("/foo").reply(200);

axios.get("/unexistent-path");

// Exception message on console:
//
// Could not find mock for: 
// {
//   "method": "get",
//   "url": "http://localhost/unexistent-path"
// }

As of 1.7.0, reply function may return a Promise:

mock.onGet("/product").reply(function (config) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (Math.random() > 0.1) {
        resolve([200, { id: 4, name: "foo" }]);
      } else {
        // reject() reason will be passed as-is.
        // Use HTTP error status code to simulate server failure.
        resolve([500, { success: false }]);
      }
    }, 1000);
  });
});

Composing from multiple sources with Promises:

var normalAxios = axios.create();
var mockAxios = axios.create();
var mock = new MockAdapter(mockAxios);

mock
  .onGet("/orders")
  .reply(() =>
    Promise.all([
      normalAxios.get("/api/v1/orders").then((resp) => resp.data),
      normalAxios.get("/api/v2/orders").then((resp) => resp.data),
      { id: "-1", content: "extra row 1" },
      { id: "-2", content: "extra row 2" },
    ]).then((sources) => [
      200,
      sources.reduce((agg, source) => agg.concat(source)),
    ])
  );

History

The history property allows you to enumerate existing axios request objects. The property is an object of verb keys referencing arrays of request objects.

This is useful for testing.

describe("Feature", () => {
  it("requests an endpoint", (done) => {
    var mock = new AxiosMockAdapter(axios);
    mock.onPost("/endpoint").replyOnce(200);

    feature
      .request()
      .then(() => {
        expect(mock.history.post.length).toBe(1);
        expect(mock.history.post[0].data).toBe(JSON.stringify({ foo: "bar" }));
      })
      .then(done)
      .catch(done.fail);
  });
});

You can clear the history with resetHistory

mock.resetHistory();

axios-mock-adapter's People

Contributors

brianmitchl avatar cross311 avatar ctimmerm avatar danii-nebot avatar davidlewallen avatar dbenchi avatar dependabot[bot] avatar domi1033 avatar gilbsgilbs avatar hlissnake avatar joebowbeer avatar koenpunt avatar marcbachmann avatar mikaoelitiana avatar mzabriskie avatar noah-potter avatar novascreen avatar peterox avatar petraszd avatar prashanth-92 avatar rafaelcaviquioli avatar remcohaszing avatar rmartins90 avatar rstein avatar sakumikko avatar starptech avatar stezu avatar tkryskiewicz avatar vshuhaiev avatar wirmar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

axios-mock-adapter's Issues

Query params not handled properly

Looks like the mock adapter is not mutating the config by changing "/path/here?param1=value" to include:

params: {
  param1: value
}

I came up with a workaround, but it is kind of sloppy. Importing the url module and doing this on many calls:

.......
mockAdapter.onGet(/\/path\/here\/?(|\?.*)).reply((config) => {
const parsedUrl = url.parse(url.resolve(config.baseURL, config.url), true, true);
config.params = parsedUrl.query;
.......

Why no send request?

I used axios-mock-adapter mock the request.if i need send a request (no mock),for example:

axios.get(`/menus/getMenus`, {params: params})
//This request i need no nock, (send true request).

Look the google chrome devtools:
image

Why no request ? please help me. Thx.

Correct way to cleanup mock

I had side effects between tests because of the mocks. I had 2 files on the following model:

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

const mock = new MockAdapter(axios)

describe('eventsActions', () => {

  afterEach(() => {
    mock.reset()
  })

  describe('changePreferences', () => {
    it('should call /api/users/preferences and dispatch events', (done) => {
      mock.onPost('/api/users/preferences')
        .reply(200)
...

When run alone, each file end with success but when run together, the calls to one url are 404.
I suspected a side effect due to poor cleaning and I looked at the tests on this repo. My tests now works by removing the afterEach and adding

beforeEach(() => {
    mock = new MockAdapter(axios)
  })

So, problem solved, but I am curious. Is this the intended use ? When am I supposed to use reset() and restore() ?

Thank you

Mocking axios.all()

Hi.
Is there a way to mock multiple get requests originally managed by the all() method?
I saw the last section of the doc ("Composing from multiple sources with Promises:") but I'm not sure this is what I need and if so how to deal with it.
Any suggestions?
Thanks.

No support for Axios Request method aliases

I saw that the findHandler does not handle the request options as object

} else if (handler[0] instanceof RegExp) {

that the cause why this doesn't works

 mock.onGet('/foo').reply(200, {
      foo: 'bar'
    });

    return instance.get({  url: '/foo'  }).then(function(response) {
      expect(response.status).to.equal(200);
      expect(response.data.foo).to.equal('bar');
    });

Here the opt is not handled as object

var handler = utils.findHandler(mockAdapter.handlers, config.method, config.url, config.data, config.params);

Inspecting request body?

I am looking for a way to verify that the JSON in my request is structured properly for the API on the server. (I don't want to match routes or methods against certain request parameters.) Is the only way to inspect the request data via the config.data property in the .reply() method?

For example, I'm doing something like this now:

mock.onPost().reply( ({data}) => { 
    expect(data.items.length).not.toBe(0);
    expect(data.title).toBe("my test title");
    // etc...
    done();
});

but using .reply() for this seems somewhat counterintuitive and I'm wondering if I'm missing something.

How to match against get params?

I'm making the following request:

axios.get('/api', { params: { name: 'Bob' }})
...

And I'm trying to mock it like so:

mock.onGet('/api', { params: { name: 'Bob' } }).reply(200, 'Hello')

But it keeps returning a 404. I also tried the following to no avail:

mock.onGet('/api', { name: 'Bob' }).reply(200, 'Hello')
mock.onGet('/api?name=Bob').reply(200, 'Hello')

The only thing that matches it is:

mock.onGet('/api').reply(200, 'Hello')

How can I match against and mock get requests with specific query params?

Match request body for PUT and POST requests

Hello!

I started to use this library since I switched my work from Angular to React and axios for http-requests. Thank you for this package, that was really a missing feature.

Now I have a lack of matching body for requests with payload. I'd like to do something like this:

mock.onPost('/api/users', {name: 'new user', email: '[email protected]'}).reply(200);

Then I can to test not only that request was actually called, but also that it has proper body. That feature was built-in in Angular's mock library, so it would be nice to have it there as well.

Intercepted HTTP method should be case insensitive

Repro:

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'

const mock = new MockAdapter(axios);

mock.onPost('/myurl').reply(200, {});

axios('/myurl', { method: 'POST' })

Expected: interceptor to work properly
Actual:

TypeError: Cannot read property 'find' of undefined

Culprit appears to be index.js line 4. If I change the http method to post instead of POST everything works as expected

Unable to call same endpoint twice with different responses

Testing some re-authentication logic that retries a request after refreshing. Snippet should be fairly explanatory:

    context('when auth token has expired', () => {
      const code = 'auth_token_expired';
      const refresh = { refresh_token: 'refresh', user: {} };
      const user = { name: 'bob' };
      const success = { results: [], totalCount: 0 };

      context('when refresh succeeds', () => {
        beforeEach(() => {
          spyOn(session, 'refreshToken').andReturn('refresh');

          mockAdapter.onGet(endpoint).replyOnce(401, { code })
            .onGet(endpoint).replyOnce(200, success)
            .onPost('/sessions/refresh').reply(200, refresh);
        });

        it('retries the original request', (done) => {
          adapter.get(endpoint).then((resp) => {
            expect(response).toEqual(success);
          }).catch(e => {
            debugger
          });
        });

The first call to endpoint gives me a 401, but the second one gives me a 404. I suspect it's due to the way I'm executing the second call:

adapter.interceptors.response.use(undefined, (error) => {
  if (error.response.status === 401) {
    if (error.response.data.code === 'auth_token_expired') {
      const refresh = session.refreshToken();

      if (refresh) {
        return adapter.post('/sessions/refresh', { refresh_token: refresh }).then((resp) => {
          session.login(resp.data);
          return adapter(error.config);
        }).catch((e) => {

When I call adapter(error.config), the effect is that the endpoint is called again, but I don't think axios-mock-adapter recognizes it as being the same call. Is this a bug, or expected? Is there a way I can work around it?

Missleading regex example

When using a regex expression, requests don't get caught by the adapter in some cases

This works :

const axios = axios.create({
  baseURL: 'https://apiurl.com'
})
axios.get('/foo/123').then(function (data) {
  console.log(data)
})

mock.onGet(/\/foo\/\d+/).reply(function(config) {
  return [200, {}];
})

This doesn't :

const axios = axios.create({
  baseURL: 'https://apiurl.com/'
})
axios.get('/foo/123').then(function (data) {
  console.log(data)
})

mock.onGet(/\/foo\/\d+/).reply(function(config) {
  return [200, {}];
})

It is due to the trailing slash in the baseURL.

Is there a way to fix that (in handleRequest function for example) or at least change the documentation ?

mock axios in module style

I got code like this

method.js

export function deleteImageFromServer(id){
	return axios.post('http://localhost:8000/'+'delete', {id:id})
}

home.spec.js

import {deleteImageFromServer} from './method'
import MockAdapter from 'axios-mock-adapter'
import axios from 'axios'
import {expect} from 'chai'

describe('deleteImageFromServer', function () {
	it('should delete image', function () {

		let mock = new MockAdapter(axios)
		mock.onPost('http://localhost:8000/delete').reply(function(){
			return [200, 'success']
		})
		deleteImageFromServer(1).then( (r) =>{
			expect(r.data).to.equal('success')
		})
	})
})

I don't know why the intercept never happens.

onGet not working anymore as expected

Hi @ctimmerm,

it seems, that 1.8.0 broke the behaviour of onGet.
Before all GET requests matching my URL defined in onGet landed the reply callback function.

Now I have to explicitly define EVERY SINGLE parameter, to have that match.

Example:

GET /users?q=Adam

mock.onGet('/users').reply(conf => {
  // not reached!!
});
mock.onGet('/users', { params: { q: 'Adam' }}).reply(conf => {
  // reached
});

lost data!!!

when i send a post request which be passed to network,the data in body lost. And it is normal after i close mock.

ver: 1.9.0, os: macOS, browser: Chrome 59.0.3071.104

Ability to define baseUrl

Hello,

I am using axios-mock-adapter with big sucees. Thank you very much for it.
However, recently I'been forced to change my app so it can be served from a subdomain.
This forced me to edit all mockup definitions, adding a base path to all of them.
It would be ideally to be able to define a baseUrl like axios allows.

thanks and regards

URL didnt matching in Get request

Hi Team,

I have a click function for fetching the records through API call, the function looks like below,

onClick(rollNo){
                    axios({
                        url: '/api/getStudentDetail/'+rollNo,
                        method: 'get',
                        headers: {                  
                            'Content-type': 'text/csv'
                        }   
                    }).then(function (successData) {
                                        console.log(successData.data);
                    }.bind(this)).catch(function (errorData) {         
                                                console.log(errorData.data);
                    }.bind(this));
}

I am trying to mock this axios call using axios mock adapter as below,

it('should test StudentContainer ', function (done) {
    const wrapper = shallow(<StudentContainer />);      
    const button= wrapper.find('button').at(0);
    var rollNo = 'A016SS1245';
    button.simulate('click', [rollNo]); 
    mock.reset();
    mock.onGet('/api/getStudentDetail/').reply(200, { 
                firstName: 'John',
                                    lastName: 'smith'
    });
    axios.get('/api/getStudentDetail/')
        .then(function(response) {
            console.log(response);
        });         
    done();                 
});     

While running this testcase, it every time execute the catch block, rather than then block. Can anyone help me on how to mock this axios call using axios mock adapter.

allow return of array as response

mock.onGet('/users').reply(200, [{
"name": "jd"
}]);

Dosen't work when it's an array.
I'm guessing it expects the response to only be an object

Allow handler to return a promise

It would be raaaad if I could do something like this:

mock.onPost(`/tests`).reply((data) => {
  return doSomething(data.data)
  .then((intermediate) => doSomethingElse(intermediate))
  .then((final) => final ? [200, final] : [404, {}])
  .catch((err) => [500, err]);
});

instead, it looks like the .reply handler expects an immediate reply, instead of a deferred.

axios baseUrl with trailing slash '/'

Hi, this might be a bit of an edge case but it did drive me crazy for a couple of hours today until I realised what was going on. Basically, there is an inconsistency in how the axios library and axios-mock-adapter behave when axios is set up with a baseUrl that contains a trailing slash.

I've set up a little test to showcase the issue:

var axios = require('axios');
var expect = require('chai').expect;
var createServer = require('http').createServer;

var MockAdapter = require('../src');

describe('trailing slash in axios baseUrl issue (requires Node)', function() {
  var instance;
  var mock;
  var httpServer;
  var serverUrl;

  before('set up Node server', function() {
    return new Promise(function(resolve, reject) {
      httpServer = createServer(function(req, resp) {
        if (req.url === '/error') {
          resp.statusCode = 500;
          resp.end();
        } else {
          resp.statusCode = 200;
          // Reply with path minus leading /
          resp.end(req.url.slice(1), 'utf8');
        }
      })
        .listen(0, '127.0.0.1', function() {
          serverUrl = 'http://127.0.0.1:' + httpServer.address().port;
          resolve();
        })
        .on('error', reject);
    });
  });

  beforeEach(function() {
    instance = axios.create({ baseURL: serverUrl + '/' }); // baseUrl has a trailing slash
    mock = new MockAdapter(instance);
  });

  it('axios should handle trailing slash in baseUrl', function() { // passes
    mock.onAny().passThrough();
    return Promise.all([
      instance.get('/foo')
      .then(function(response) {
        expect(response.status).to.equal(200);
        expect(response.data).to.equal('foo');
      }),
      instance.get('foo')
        .then(function(response) {
          expect(response.status).to.equal(200);
          expect(response.data).to.equal('foo');
        })
    ]);
  });

  it('mock adapter should handle trailing slash in baseUrl', function() { // both fail: 404
    mock.onGet('/foo').reply(200, 'bar');
    return Promise.all([
      instance.get('/foo')
      .then(function(response) {
        expect(response.status).to.equal(200);
        expect(response.data).to.equal('bar');
      }),
      instance.get('foo')
      .then(function(response) {
        expect(response.status).to.equal(200);
        expect(response.data).to.equal('bar');
      })
    ]);
  });
});

I'll open a PR with a fix, as I think it's important that we should mimic axios behaviour seamlessly.

URL didnt matching in Get request

Hi Team,

I have a click function for fetching the records through API call, the function looks like below,

onClick(rollNo){
                    axios({
                        url: '/api/getStudentDetail/'+rollNo,
                        method: 'get',
                        headers: {                  
                            'Content-type': 'text/csv'
                        }   
                    }).then(function (successData) {
                                        console.log(successData.data);
                    }.bind(this)).catch(function (errorData) {         
                                                console.log(errorData.data);
                    }.bind(this));
}

I am trying to mock this axios call using axios mock adapter as below,

it('should test StudentContainer ', function (done) {
    const wrapper = shallow(<StudentContainer />);      
    const button= wrapper.find('button').at(0);
    var rollNo = 'A016SS1245';
    mock.reset();
    mock.onGet('/api/getStudentDetail/' + rollNo).reply(200, { 
                firstName: 'John',
                                    lastName: 'smith'
    });
            button.simulate('click', [rollNo]); 
    axios.get('/api/getStudentDetail/')
        .then(function(response) {
            console.log(response);
        });         
    done();                 
});     

While running this testcase, it every time execute the catch block, rather than then block. Can anyone help me on how to mock this axios call using axios mock adapter.

@ctimmerm, also i tried as you said in previous post its not working, and this is the respone i get when i run the test script,

Error: the object {

"config": {
"adapter": [Function]
"data": [undefined]
"headers": {
"Accept": "application/json, text/plain, /"
}
"maxContentLength": -1
"method": "get"
"timeout": 0
"transformRequest": {
"0": [Function]
}
"transformResponse": {
"0": [Function]
}
"url": '/api/getStudentDetail/'
"validateStatus": [Function]
"withCredentials": [undefined]
"xsrfCookieName": "XSRF-TOKEN"
"xsrfHeaderName": "X-XSRF-TOKEN"
}
"status": 404
was thrown, throw an Error :)

Could you please help me in resolving this issue.

Example of passing arguments

Hi,

Trying to write an onPost that checks the arguments passed, but not having any luck. Dug through your source code, but what would be really helpful would be at least one example in the README of using arguments in the request:

My Code

Axios.post('/api/estimate', {
      _id: '123'
})

This "works" but doesn't check arguments:

mockServer.onPost('/api/estimate').reply(200, { text: 'stuff to reply with' })

This doesn't work:

mockServer.onPost('/api/estimate', {
  _id: '123'
}).reply(200, { text: 'stuff to reply with' })

Also doesn't work

mockServer.onPost('/api/estimate', {
  request:
    _id: '123'
  }
}).reply(200, { text: 'stuff to reply with' })

Also doesn't work

mockServer.onPost('/api/estimate', {
  body:
    _id: '123'
  }
}).reply(200, { text: 'stuff to reply with' })

Etc. You get the idea. Would be really helpful if you could provide just one simple example... Thank you!

passThrough cause axios error

// error code
import Axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(Axios);
// start mock 
mock.onAny().passThrough();
// end mock

Axios.get('/host/path')

error pic

// correct code
import Axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(Axios);
// start mock
mock.onAny().passThrough();
// end mock

const axiosIns = Axios.create();
axiosIns.get('/host/path')

Axios.create is not a function

Hi @ctimmerm,

I'm having an "axios.create() is not a function error" when i try to use axios-mock-adapter. Here's the implementation.
`

      import axios from 'axios';
      import MockAdapter from 'axios-mock-adapter';

      let mock = new MockAdapter(axios);
       mock.onGet('https://myapi.org/v1/', { params: { param1: 'holiday', sortBy:'top' } }).reply(200, {
		  	data: [{
				     author: "Vivian Michaels",
				}]
                              });

      axios.get('https://myapi.org/v1/', { params: { param1: 'holiday', sortBy:'top' } })
		  .then(function(response) {
		    console.log(response.data);
		 });`

I'm doing exactly as the documentation says but then i get the error: TypeError: axios.create is not a function. Any help is appreciated.

Axios baseUrl didn't match the Mocking

Hi, my current project has a baseUrl for our Axios instance, and the mocking is not working.
After check axios-mock-adapter source code. It seems like when u add url matcher, it doesn't add axios baseUrl in the handlers array.

Axios will merge the url and baseUrl before call the actual adapter, So I think you should consider about this.

//line 7 on index.js
function adapter() {
    var url = config.url.slice(config.baseURL ? config.baseURL.length : 0);
    var handler = utils.findHandler(this.handlers, config.method, url);

New response object on invoking request

Mock should do deep clone and return new response every time it is invoked. Example if we set below mock

mock.onGet('/users').reply(200, {
  someProp: [
    { 
     id: 1,
     nextLevel: {
        nestedProp: "Hi this value will be shared with all the response generated by this mock"
     }
    }
  ]
})

and if we test below in actual function

var someState = ...
var someFunc = function() {
axios.get('/users')
  .then(function(response) {
    // some modification in someState based on response.data.someProp[0].nextLevel.nestedProp
    // also some change in nestedProp
  });
}

if we test above function multiple times change in nestedProp will be carried forward to other test cases

passThrough infinite loop

Doing this request

  return axios({
    method: method,
    url: uri,
    headers: {
      'PRIVATE-TOKEN': GITLAB_TOKEN
    },
    data: body || {},
    params: query || {}
  })
  .then(response => {
    if (response.status === 429) {
      throw new Error('gitlab rate limit reached')
    }

    console.log(response)
  })
  .catch(err => {
    console.log(err)
  })

with

const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')

const mock = new MockAdapter(axios)

require('./blog')(mock)

mock.onAny().passThrough()

blog.js looks like this

module.exports = function (mock) {
  mock.onGet(/^\/api\/blog/).reply(200, [
    {
      Title: 'Item 1',
      Content: 'Much content here'
    },
    {
      Title: 'Item 2',
      Content: 'Much much content here'
    }
  ])
}

The blog mock is unrelated to the above axios request. No other mocking is done, its very basic right now.

This results in page being unresponsive, until it runs out of memory.

Ability to mock network failure?

Question: Is there a method to mock a network failure, say if the browser was offline trying to connect to an online resource?

Would love to have a workaround for this timeout

In Angular testing for a service that implements $http, we're using to doing this:

$httpBackend.flush();

What this does is it takes any outstanding requests and processes them so that you can then begin the assertion process. See its docs for more.

Anyway, I'm bringing this up as an example because it would be really nice to be able to have this for the axios mocker. Instead of this flush() method or something similar, we're forced to create a timeout with a zero millisecond duration and then nest all of our expectations within that timeout. For an example of this, see here:

import { expect } from 'chai';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { fetchPost } from './lib'

describe('Lib', () => {
  it('Should return data from response', (done) => {
    let mockAdapter = new MockAdapter(axios);

     mockAdapter.onGet('http://awesome.com/posts').reply(200, {
       data: {
         posts: ['Intro to git']
       }
     });

     let response = fetchPost();

     setTimeout(() => {
        expect(response.posts[0]).to.be.equal('Intro to git');
        done();
     }, 0)
  });
});

I've confirmed in my own local code that without the timeout, you indeed cannot expect response.posts[0] to be resolved, but you can inside the timeout. I don't like this syntax though because it forces all of the code to be nested another level, it's not as linear, and it assumes some things about how your axios promiser is implemented (e.g. it breaks on an otherwise perfectly functioning custom wrapper that I wrote for fun).

Would it be possible to have some sort of $httpBackend.flush(); equivalent for this axios mocker?

Thanks!

.onAny() not working as expected

I have my mocks set up like to:

mock
  .onGet('/foo').reply(200)
  .onAny().reply(500);

However, when I make a request to /bar, a 404 code is returned instead of my specified 500. Changing this to .onAny('/bar') or .onAny(/.*/) works as expected.

I am using axios v0.14.0 and axios-mock-adapter v1.6.1.

custom response body

Is there a way that we can customize the response? For example, I would like to change the name of data to json in the response to match our actual data. Anyway currently available to do that or is this something you would consider adding?

Cannot set property 'handlers' of undefined

Hi, I don't know what I'm doing wrong but every time I try to mock axios it raises this exception:
TypeError: Cannot set property 'handlers' of undefined
at reset (node_modules/axios-mock-adapter/src/index.js:23:17)
at MockAdapter (node_modules/axios-mock-adapter/src/index.js:31:9)

Digging into the source code I can see that it's happening when creating a new mock, my code is like this:

import Axios from 'axios';
import mockAdapter from 'axios-mock-adapter';
...
const httpMock = mockAdapter(Axios); // here it raises the exception
httpMock.onGet('/providers').reply(200, ['Provider1', 'Provider2', 'Provider3']);

Thanks in advance

Ability to switch mocking `on` and `off`

I would be nice to have the ability to turn mocking on during development. The library currently has the method reset, which removes the handlers, and restore which removes mocking from axios. However, there is currently no possiblity to stop mocking, remember the added handlers and start mocking again. Think the opposite of restore, but on an already initialized adapter.

Or it's already possible and I can't figure out why.

Works with auth?

Great library! Working great for most of my tests.

On this occasion I'm trying to test my async login actions in redux as follows:

action:

export const submitLoginData = (data, location) => dispatch => {
    dispatch(loggingIn());
    return axios({
        method: 'get',
        url: '/api/authorize',
        auth: {
            username: data.email,
            password: data.password
        }
    })

etc.

test:

            let postData = {
                email: 'Joe',
                password: 'Bloggs'
            };

            let responseData = {
                token: 'foo'
            };

            mock.onGet('/api/authorize')
                .reply(200, responseData);

            store = mockStore();

            return store.dispatch(actions.submitLoginData(postData, '/'))
                .then(() => {
                    actual = store.getActions();

                    expected = [
                        { type: actions.LOGGING_IN },
                        { type: actions.LOGIN_SUCCESS }
                    ];

                    expect(actual).to.eql(expected);
                    done();
                });

However I'm getting a 404 error. Could this be because I need to configure the route to correctly respond to HTTP basic auth? Has anyone achieved this previously?

request .onPost Then return 404

hi
Writing test code

    describe('MemberAction', () => {
	beforeEach(() => {
		mock = new MockAdapter(axios, {delayResponse:10 });
		const middlewares = [ thunk ];
		mockStore = configureMockStore(middlewares);
		store = mockStore({ actions: [] })
	});
        describe('member Join',()=>{
            beforeEach(() => {
                mock.onPost(`/account/actors/23/set_student_member/`,{"human_name":"child","is_male":true,"birthday":"2014-10-30"}).reply(200, setStudentMemberRes)
            }
            it(('regist join')=>{
                //call post /account/actors/23/set_student_member/ 
            })
        })
    }

Error: Request failed with status code 404

     config: 
       { adapter: null,
         transformRequest: { '0': [Function: transformRequest] },
         transformResponse: { '0': [Function: transformResponse] },
         timeout: 0,
         xsrfCookieName: 'XSRF-TOKEN',
         xsrfHeaderName: 'X-CSRFToken',
         maxContentLength: -1,
         validateStatus: [Function: validateStatus],
         headers: 
          { Accept: 'application/json, text/plain, */*',
            'Content-Type': 'application/json;charset=utf-8' },
         withCredentials: true,
         method: 'post',
         url: '/account/actors/23/set_student_member/',
         data: '{"human_name":"child","is_male":false,"birthday":"2016-11-29"}' },

Is anything expected?

How to use with ES6?

I have tried

import {MockAdapter} from 'axios-mock-adapter';

but MockAdapter is undefined

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.