Wie teste ich Axios im Scherz?

78

Ich habe diese Aktion in Reaktion

export function fetchPosts() {
    const request = axios.get(`${WORDPRESS_URL}`);
    return {
        type: FETCH_POSTS,
        payload: request
    }
}

Wie teste ich in diesem Fall Axios? Jest haben diesen Anwendungsfall auf der Website für asynchronen Code, wo sie eine Scheinfunktion verwenden, aber ich weiß nicht, ob ich dies mit Axios tun kann? ref: https://facebook.github.io/jest/docs/tutorial-async.html

Ich habe dies bisher getan, um zu testen, ob der richtige Typ zurückgegeben wird

it('should dispatch actions with the correct type', () => {
    store.dispatch(fetchPosts());
    let action = store.getActions();
    expect(action[0].type).toBe(FETCH_POSTS);
});

Ich habe keine Ahnung, wie ich Scheindaten übergeben und testen soll, ob sie zurückgegeben werden. Hat jemand irgendwelche Ideen?

Danke im Voraus

Adear
quelle
2
github.com/mzabriskie/moxios
Yury Tarabanko

Antworten:

60

Ich habe Axios-Mock-Adapter verwendet. In diesem Fall wird der Dienst in ./chatbot beschrieben. Im Mock-Adapter geben Sie an, was zurückgegeben werden soll, wenn der API-Endpunkt verwendet wird.

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import chatbot from './chatbot';

describe('Chatbot', () => {
    it('returns data when sendMessage is called', done => {
        var mock = new MockAdapter(axios);
        const data = { response: true };
        mock.onGet('https://us-central1-hutoma-backend.cloudfunctions.net/chat').reply(200, data);

        chatbot.sendMessage(0, 'any').then(response => {
            expect(response).toEqual(data);
            done();
        });
    });
});

Sie können das ganze Beispiel hier sehen:

Service: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.js

Test: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.test.js

Luis Nolazco
quelle
108

Ohne andere Bibliotheken zu verwenden:

import * as axios from "axios";

// Mock out all top level functions, such as get, put, delete and post:
jest.mock("axios");

// ...

test("good response", () => {
  axios.get.mockImplementation(() => Promise.resolve({ data: {...} }));
  // ...
});

test("bad response", () => {
  axios.get.mockImplementation(() => Promise.reject({ ... }));
  // ...
});

Es ist möglich, den Antwortcode anzugeben:

axios.get.mockImplementation(() => Promise.resolve({ status: 200, data: {...} }));

Es ist möglich, das Modell basierend auf den Parametern zu ändern:

axios.get.mockImplementation((url) => {
    if (url === 'www.example.com') {
        return Promise.resolve({ data: {...} });
    } else {
        //...
    }
});

Jest v23 führte syntaktischen Zucker ein, um Versprechen zu verspotten:

axios.get.mockImplementation(() => Promise.resolve({ data: {...} }));

kann vereinfacht werden

axios.get.mockResolvedValue({ data: {...} });

Es gibt auch ein Äquivalent für abgelehnte Versprechen : mockRejectedValue.

Weiterführende Literatur:

Ein Glas Ton
quelle
28

Ich könnte das folgendermaßen tun:

  1. Erstellen Sie einen Ordner __mocks __ / (wie im Kommentar von @Januartha angegeben)
  2. Implementieren Sie eine axios.jsMock-Datei
  3. Verwenden Sie mein implementiertes Modul beim Test

Der Mock wird automatisch stattfinden

Beispiel für das Mock-Modul:

module.exports = {
    get: jest.fn((url) => {
        if (url === '/something') {
            return Promise.resolve({
                data: 'data'
            });
        }
    }),
    post: jest.fn((url) => {
        if (url === '/something') {
            return Promise.resolve({
                data: 'data'
            });
        }
        if (url === '/something2') {
            return Promise.resolve({
                data: 'data2'
            });
        }
    }),
    create: jest.fn(function () {
        return this;
    })
};
Amadeu Cavalcante Filho
quelle
1
Hi @ shorif2000 Ich habe es hier implementiert github.com/vspedr/movile-messaging/pull/8/files
Amadeu Cavalcante Filho
1
Das Schreiben von manuellen Verspottungen innerhalb von Verspottungen ist keine gute Praxis, da in der Dokumentation zu manuellen Verspottungen
angegeben ist
@ Januartha Entschuldigung, für meinen Tippfehler. Ich werde es hier korrigieren. Ich tippte die Antwort "____mock___" ein und mein Wort wurde fett gedruckt. Entschuldigung
Amadeu Cavalcante Filho
@ AmadeuCavalcanteFilho ah sicher, kein Problem :)
Januartha
3

Ich habe das mit Nock gemacht , so:

import nock from 'nock'
import axios from 'axios'
import httpAdapter from 'axios/lib/adapters/http'

axios.defaults.adapter = httpAdapter

describe('foo', () => {
    it('bar', () => {
        nock('https://example.com:443')
            .get('/example')
            .reply(200, 'some payload')

        // test...
    })
})
Jon B.
quelle
1
Ich habe es versucht, aber ich scheine, dass Axios nicht gut mit Nock spielen. github.com/node-nock/nock/issues/699, aber danke für Ihre Hilfe trotzdem
Adear
0

Für diejenigen, die Axios-Mock-Adapter anstelle des Mockfetch-Beispiels in der Redux-Dokumentation für asynchrone Tests verwenden möchten , habe ich Folgendes erfolgreich verwendet

actions.test.js::

describe('SignInUser', () => {
  var history = {
    push: function(str) {
        expect(str).toEqual('/feed');
    }
  }

  it('Dispatches authorization', () => {
    let mock = new MockAdapter(axios);
    mock.onPost(`${ROOT_URL}/auth/signin`, { 
        email: '[email protected]', 
        password: 'test'
    }).reply(200, {token: 'testToken' });

    const expectedActions = [ { type: types.AUTH_USER } ];
    const store = mockStore({ auth: [] });

    return store.dispatch(actions.signInUser({ 
      email: '[email protected]', 
      password: 'test',
    }, history)).then(() => {
        expect(store.getActions()).toEqual(expectedActions);
  });

});

Um einen erfolgreichen Fall für signInUserin zu testen actions/index.js:

export const signInUser = ({ email, password }, history) => async dispatch => {
  const res = await axios.post(`${ROOT_URL}/auth/signin`, { email, password })
    .catch(({ response: { data } }) => {
        ...
  });

  if (res) {
    dispatch({ type: AUTH_USER });                 // test verified this
    localStorage.setItem('token', res.data.token); // test mocked this
    history.push('/feed');                         // test mocked this
  }
}

Da dies mit Scherz gemacht wird, musste der Localstorage-Aufruf verspottet werden. Dies war in src/setupTests.js:

const localStorageMock = {
  removeItem: jest.fn(),
  getItem: jest.fn(),
  setItem: jest.fn(),
  clear: jest.fn()
};
global.localStorage = localStorageMock;
Vapurrmaid
quelle
Wie haben Sie den localStorageMock
Kermit_ice_tea
@Kermit_ice_tea src/setupTests.jsist in der Create-React -App als globales Setup für Scherz- / Enzymtests dokumentiert. In dieser Datei habe ich ein Objekt erstellt, das ich willkürlich localStorageMockmit Dummy-Funktionen (getItem, setItem) aufgerufen habe. Die Magie ist unten, wo ich global.localStoragedieses Objekt gleichgesetzt habe. Ich hätte dies in einer Zeile tun können, anstatt das Objekt localStorageMock zu benennen. Der Zweck dieses gesamten Setups bestand darin, einfach zu verhindern, dass Code, der sich mit localstorage befasst, während der Tests beschädigt wird.
Vapurrmaid