Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redux - how use nock to test async action

I follow the basic exmaple of redux.org to test async action

action.js

my code is like this:

import axios from 'axios'

export function getGoodDataStart(){
    return{
        type: "GOOD_DATA_START"
    }
}
export function getGoodDataSuccess(payload){
    console.log('success', payload)
    return {
        type: "GOOD_DATA_SUCCESS",
        payload: payload
    }
}
export function getGoodDataFail(){
    return{
        type: "GOOD_DATA_FAIL"
    }
}
export function getGoodData(){
    return (dispatch) => {
        dispatch( getGoodDataStart() )
        return  axios.get('http://www.google.com/list')
            .then( response => {
                console.log('fake res',response)
                dispatch(getGoodDataSuccess (response) )
            })
            .catch( err => {
                console.log('fake err',err)
            })
    }   
}
    

test.js

import nock from 'nock'
import React from 'react'
import {expect} from 'chai'
import {getGoodData} from 'registerAction'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)

describe('Register component', () => {

    it('async action', function () {

        nock('http://www.google.com')
        .get('/list')
        .reply(200,'ok!' )

        const store = mockStore({ 
            myData: '' ,
        })
        const expected = [
            {type: "GOOD_DATA_START"},
            {type: "GOOD_DATA_SUCCESS", payload: 'ok!'}
        ]

        return store.dispatch(getGoodData())
            .then( () => { 
                expect(store.getActions()).to.equal(expected)
            })
    })
})

The problem I have is, nock is not blocking the request

like image 635
angry kiwi Avatar asked Oct 31 '25 04:10

angry kiwi


1 Answers

Typically when testing an action like this you'll want to remove anything that is not part of your action from the equation. In this case by simply using nock, you're not removing axios from the equation and are actually adding unnecessary complexity. By mocking axios with a spy, you avoid making the network call and you also avoid calling axios at all. This allows you to simply assert that axios is called with the correct parameters. The spy can return a promise that allows testing all the promise handling and subsequent action calls. In order to demonstrate this, I needed to add a library that provides spies, so I opted to add 'expect' for both assertions and spies, but you could easily do the same thing with sinon if you want to stick with chai.

Here's an example where you don't need nock at all and you just mock axios with a spy:

import React from 'react'
import * as registerAction from 'registerAction'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import expect from 'expect'

const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)

// set up to mock axios methods
import axios from 'axios'
const _get = axios.get

const fakePayload = { foo: 'bar' };
describe('Register component', () => {
    beforeEach(() => {
        // replace the .get method temporarily with a spy
        axios.get = expect.createSpy().andReturn(Promise.resolve(fakePayload));
    })

    afterEach(() => {
        // restore the get method with our saved const
        axios.get = _get;
    })

    it('async action', function () {
        const store = mockStore({
            myData: '' ,
        })
        const expected = [
            {type: "GOOD_DATA_START"},
            {type: "GOOD_DATA_SUCCESS", payload: fakePayload}
        ]

        return store.dispatch(registerAction.getGoodData())
            .then( () => {
                expect(store.getActions()).toEqual(expected)
                expect(axios.get).toHaveBeenCalled()
                expect(axios.get).toHaveBeenCalledWith('http://www.google.com/list')
            })
    })
})
like image 118
Ben Sidelinger Avatar answered Nov 03 '25 11:11

Ben Sidelinger