DEV Community

Konrad Lisiczyński
Konrad Lisiczyński

Posted on • Updated on

Taming network with redux-requests, part 8 - Mocking and multiple drivers

In the previous part of this series we discussed caching.

In this part we will cover mocking and a possibility to use multiple drivers in one app.

What is mocking and when it is useful?

Mocking is like faking. Sometimes, usually as front-end developer you happen to be in a position when you need to work on a feature but this feature requires to integrate with back-end. Often back-end could be not ready yet or just buggy. Not always you can afford to wait, what to do then? The answer is mocking. You can mock some server responses and start working before API is finished, and then, once it is, you can replace mocked responses with real ones. In real life this happens so often that it would be great to make this process as easy as possible. Fortunately redux-requests has a dedicated driver for such a situation!

Using mock driver

As you probably noticed, redux-requests supports drivers concept. You can use it with axios, Fetch API, GraphQL, anything! You can write your own drivers. You can even use multiple at the same time. One of those drivers is mock driver. Let's see how to use it and how it could help us when we don't have back-end finished and we want to start working.

To install the package, just run:

$ npm install @redux-requests/mock

Then, as always, pass it to handleRequests first:

import { handleRequests } from '@redux-requests/core';
import { createDriver } from '@redux-requests/mock';

handleRequests({
  driver: createDriver({
    // optional, in ms, defining how much time mock request would take, useful for testing spinners
    timeout: 1000,
  }),
});

Then, start using it inside your request actions:

const fetchPhoto = id => ({
  type: FETCH_PHOTO,
  request: {
    response: {
      data: {
        id,
        title: 'accusamus beatae ad facilis cum similique qui sunt',
      },
    },
  },
});

const fetchPhotoWhichWillFail = id => ({
  type: FETCH_PHOTO_WHICH_WILL_FAIL,
  request: {
    error: { status: 404 },
  },
});

Also note, that for mutations you need to pass meta.asMutation: true in your request actions, so the core library could know whether a request is a query or a mutation. For many drivers like axios, fetch and graphql it is not usually necessary as the library can deduct whether something is a query or a mutation by looking at request config, like GET request method will be typically a query while POST a mutation.

Anyway, this is all there is to it! Then, once part/all of mocked endpoints are finished, all you need to do is to replace mock driver with something else, like axios. All other things will become unchanged. This is one of the reasons why driver approach could be handy.

Ok, but there is one last thing. Usually you won't mock everything. So how to use mock driver for some actions and another like axios in others? For that you need to use multiple drivers.

Using multiple drivers

Multiple drivers are useful especially for mocking scenario. But it could be also great if for instance you use multiple ways to communicate with server/servers, like axios together with graphql. In could be also useful when you would like to switch from axios to Fetch API for instance without refactoring everything at the same time, but gradually. Anyway, let's see how to do it with axios and mock drivers together:

import axios from 'axios';
import { handleRequests } from '@redux-requests/core';
import { createDriver as createAxiosDriver } from '@redux-requests/axios';
import { createDriver as createMockDriver } from '@redux-requests/mock';

handleRequests({
  driver: {
    default: createAxiosDriver(axios),
    mock: createMockDriver({ timeout: 1000 }),
  },
});

As you can see, the default driver is axios, so how to mark a request to be run by mock driver? Just pass the key you assigned to mock driver (mock in our case) in action.meta.driver, for instance:

const fetchPhoto = id => ({
  type: FETCH_PHOTO,
  request: {
    response: {
      data: {
        id,
        title: 'accusamus beatae ad facilis cum similique qui sunt',
      },
    },
  },
  meta: { driver: 'mock' },
});

Then, once fetchPhoto is ready on the back-end, you could refactor it to something like that:

const fetchPhoto = id => ({
  type: FETCH_PHOTO,
  request: {
    url: `/photo/${id}`,
  },
});

With such an approach, you could really surprise your team, you could easily integrate your app with a new and shiny back-end in minutes!

What's next?

In the next part we will cover using redux-requests with promise based libraries.

Top comments (0)