Jest / Enzyme: Как обработать функцию asyn c, вызываемую внутри другой? - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь запустить Jest / Enzyme asyn c тесты для fetchTemperatures, и я наткнулся на немного незнакомого места. Если я определю долготу и широту и закомментирую getUserCoordinates, я смогу пройти мои тесты. Вопрос в том, как мне написать свои тесты, чтобы разрешить / смоделировать, что функция asyn c внутри fetchTemperatures возвращает значения?

~ дополнительно, если есть какие-либо другие проблемы с тем, как написан код пожалуйста, дайте мне знать, я пытаюсь вернуться к среде js ...

fetchTemperas. js

export const fetchTemperatures = async (format = 'weather', source = 'openWeather') => {
    // for 5-day-forecast set format arg to "forecast"
    try {
        let response;
        const { longitude, latitude } = await getUserCoordinates();
        //! the nested async above is preventing me from running the tests...
        // let longitude = 100;
        // let latitude = 100;
        if (source === 'openWeather') {
            response = await fetch(
                `${openWeatherURL}/${format}?APPID=${process.env
                    .REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
            );
        } else if (source === 'darkSky') {
            response = await fetch(
                `${darkSkyURL}${process.env
                    .REACT_APP_DS_API_KEY}/${latitude},${longitude}?exclude=[currently,minutely,hourly,flags]`
            );
        } else {
            //! is this getting hit? -- not sure
            throw new Error("Enter a valid source string. Ex: 'openWeather' or 'darkSky'");
        }
        return await response.json();
    } catch (error) {
        throw new Error('Fetch failed');
    }
};

fetchTemperas.test. js


describe('fetchTemperatures()', () => {
    let mockResponse = { data: 'Weather related data.' };
    let response;
    beforeAll(() => {
        window.fetch = jest.fn().mockImplementation(() => {
            return Promise.resolve({
                ok: true,
                json: () => Promise.resolve(mockResponse)
            });
        });
        //! Number of calls: 0 === FIGURE OUT NESTED ASYNC IN SOURCE
        response = fetchTemperatures();
    });

    // argument-based routes
    it('args=default, should call fetch with the correct url', () => {
        fetchTemperatures();
        expect(window.fetch).toHaveBeenCalledWith(
            `${openWeatherURL}/weather?APPID=${process.env
                .REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
        );
    });
    it('args="weather", should call fetch with the correct url', () => {
        fetchTemperatures('forecast');
        expect(window.fetch).toHaveBeenCalledWith(
            `${openWeatherURL}/weather?APPID=${process.env
                .REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
        );
    });
    it('args="weather", "darkSky", should call fetch with the correct url', () => {
        fetchTemperatures('weather', 'darkSky');
        expect(window.fetch).toHaveBeenCalledWith(
            `${darkSkyURL}${process.env
                .REACT_APP_DS_API_KEY}/${latitude},${longitude}?exclude=[currently,minutely,hourly,flags]`
        );
    });

    // success
    it('Success::Promise Resolve: should return with the current weather', () => {
        response.then((results) => {
            expect(results).toEqual(mockResponse);
        });
    });

    // failure - success but response not ok
    it('Failure::Response !ok: should return an error', () => {
        window.fetch = jest.fn().mockImplementation(() => {
            return Promise.resolve({
                ok: false
            });
        });
        expect(fetchTemperatures()).rejects.toEqual(Error('Fetch failed'));
    });

    // failure - reject
    it('Failure::Promise Rejects', () => {
        window.fetch = jest.fn().mockImplementation(() => {
            return Promise.reject(Error('Fetch failed'));
        });
        expect(fetchTemperatures()).rejects.toEqual(Error('Fetch failed'));
    });
});

1 Ответ

1 голос
/ 23 января 2020

Довольно просто смоделировать getUserCoordinates, у вас есть несколько разных опций:

  1. Вы можете использовать jest.mock, который берет путь к модулю, содержащему getUserCoordinates, и перехватывает его, возвращая ложное значение из предоставленного вами обратного вызова:
// This assumes `getUserCoordinates` is a named export.
// If it's the default export just have the callback return jest.fn()...
jest.mock('./get-user-coordinates.js', () => ({
  getUserCoordinates: jest.fn().mockResolvedValue({lat: 0, long: 0});
}));
Вы также можете использовать import * as, который позволяет имитировать импорт без jest.mock:
// You can name `api` whatever you want
import * as api from './get-user-coordinates';

api.getUserCoordinates = jest.fn().mockResolvedValue({lat: 0, long: 0});

И еще одна вещь: в третьем тесте вы должны выполнить Обязательно верните response.then()..., иначе ваш тест пройдет, прежде чем ждать ввода блока .then():

// Returning the promise makes the test wait until the
// `.then` is executed before finishing.
return response.then((results) => {
  expect(results).toEqual(mockResponse);
});
...