Як протестувати аксіо в Jest?


81

У мене така дія в React:

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

Як протестувати Axios у цьому випадку?

У Jest на цьому сайті є такий варіант використання асинхронного коду, де вони використовують макетну функцію, але чи можу я це зробити з Axios?

Довідково: Приклад асинхронізації

Я зробив це до цього часу, щоб перевірити, чи повертає він правильний тип:

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

Як я можу передати фіктивні дані та перевірити їх повернення?


Відповіді:


65

Я використовував axios-mock-adapter. У цьому випадку послуга описана в ./chatbot. У макетному адаптері ви вказуєте, що повертати, коли споживається кінцева точка API.

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();
        });
    });
});

Повний приклад ви можете побачити тут:

Послуга: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.js

Тест: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.test.js


114

Без використання інших бібліотек:

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({ ... }));
  // ...
});

Можна вказати код відповіді:

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

Можна змінити макет на основі параметрів:

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

Jest v23 представив трохи синтаксичного цукру для насмішок над обіцянками:

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

Це можна спростити

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

Існує також еквівалент відхилених обіцянок: mockRejectedValue.

Подальше читання:


28

Я міг би зробити це, виконавши кроки:

  1. Створіть папку __mocks __ / (як зазначив коментар @Januartha)
  2. Впровадити axios.jsфальшивий файл
  3. Використовуйте мій реалізований модуль на тесті

Знущання відбуватиметься автоматично

Приклад макетного модуля:

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;
    })
};

1
Привіт @ shorif2000 Я реалізував це тут github.com/vspedr/movile-messaging/pull/8/files
Amadeu Cavalcante Filho

1
писати вручну знущається всередині знущається не є доброю практикою , як документація по експлуатації знущається говорить писати вручну знущається всередині __mocks__
Januartha

@Januartha вибачте, за мій неправильний тип. Я збираюся це виправити тут. Я набрав відповідь "____mock___", і моє слово було напівжирним. Вибачте
Amadeu Cavalcante Filho

@AmadeuCavalcanteFilho ах, звичайно, не біда :)
Januartha

3

Я зробив це з nock , приблизно так:

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...
    })
})

1
Я спробував це, але мені здається, що axios погано грає з nock. github.com/node-nock/nock/issues/699, але тим не менше дякую за вашу допомогу
Adear

0

Для тих, хто хоче використовувати axios-mock-adapter замість прикладу mockfetch у документації Redux для асинхронного тестування , я успішно використав наступне:

Файл 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: 'test@test.com',
        password: 'test'
    }).reply(200, {token: 'testToken' });

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

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

});

Для того, щоб перевірити успішний випадок signInUserу файлі action / 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
  }
}

Враховуючи, що це робиться на жарт, з виклику місцевого сховища довелося глузувати. Це було у файлі src / setupTests.js :

const localStorageMock = {
  removeItem: jest.fn(),
  getItem: jest.fn(),
  setItem: jest.fn(),
  clear: jest.fn()
};
global.localStorage = localStorageMock;

Як ви використовували localStorageMock
Kermit_ice_tea

@Kermit_ice_tea src/setupTests.jsзадокументований у програмі create- response -app як загальна установка для тестування жартів / ферментів. У цьому файлі я створив об'єкт, який довільно викликав localStorageMockфіктивними функціями (getItem, setItem). Магія знаходиться внизу, де я встановив global.localStorageрівний цьому об’єкту. Я міг зробити це в один рядок, замість того, щоб називати об’єкт localStorageMock. Метою всієї цієї установки було просто уникнути злому будь-якого коду, що має справу з localstorage, під час тестів.
vapurrmaid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.