Как мне издеваться над двумя выборками или одним обещанием и одним выборкой? - PullRequest
0 голосов
/ 08 июня 2018

Я пытаюсь проверить функцию loadAllProjects.

Тест завершается при .then () с ошибкой: TypeError: Невозможно прочитать свойство 'then' с неопределенным значением

Я также пытался высмеять ответ getHeadersWithToken (), но не смог его получитьработать.

Snookeed на этом и был бы признателен за любую помощь.

test:

    it('should create SET_ALL_PROJECTS action when fetching projects', () => {
        fetch
            .once(JSON.stringify([{ access_token: "12345" }]))
            .once(JSON.stringify({ name: "x" }))

        const expectedActions = [
            { type: "SET_ALL_PROJECTS", json: { name: "x" } },
        ]

        store.dispatch(actions.loadAllProjects.apply())
            .then(() => {     // FAILS HERE
                expect(store.getActions()).toEqual(expectedActions)
            })

    });

код:

    export const getHeadersWithToken = () => {
        return fetch("/.auth/me", requestOptions)
            .then(parseResponseAndHandleErrors)
            .then(json => {
                const header = 'Bearer ' + json[0].access_token
                const applicationJsonHeaders = getJsonHeaders(header)
                return applicationJsonHeaders
            })
            .catch( error=> {
                console.error(error)
            })
    }

    export const loadAllProjects = () => {
        return (dispatch) => {
            getHeadersWithToken()
                .then(applicationJsonHeaders => {
                    const requestOptions = {
                        method: 'GET',
                        headers: applicationJsonHeaders,
                    };
                    return fetch(process.env.REACT_APP_PROJECTS_API_URL + "/projects", requestOptions)
                        .then(parseResponseAndHandleErrors)
                        .then(json => {
                            dispatch(setAllProjects(json))})
                        .catch(error => {
                            console.error(error)
                            dispatch(failedToLoadProjects(error))
                        });
                })
        }
    }

магазин используется в test:

    const store = mockStore(Map(
        {
            allProjects: Map({
            }),
            currentProject: Map({

                authenticationData: Map({

                })
            })
        })

    );

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

На случай, если это когда-нибудь пригодится кому-либо и в подтверждение ответа Septastium, я в итоге изменил код на:

async getHeadersWithToken(requestType) {
    if (process.env.REACT_APP_RUNNING_LOCALLY==="true") {
        return {
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/json'
        };
    }
    let result = await fetch("/.auth/me", this.requestOptions)
    let headers = result.json()
        .then( json => {
            const header = 'Bearer ' + json[0].access_token
            const applicationJsonHeaders = this.getJsonHeaders(header, requestType)
            return applicationJsonHeaders
        })
        .catch(error => {
            console.error(error)
        })
    return headers
}

export const loadAllProjects = () => {
    return async dispatch => {
        const authenticator = new Authenticator()
        let applicationJsonHeaders = await authenticator.getHeadersWithToken(constants.GET)
        let loggedInUser = await authenticator.getLoggedInUser()
        const requestOptions = {
            method: 'GET',
            headers: applicationJsonHeaders,
        };
        return await fetch(process.env.REACT_APP_PROJECTS_API_URL + "/projects", requestOptions)
            .then(response => {
                return parseResponseAndHandleErrors(response)
            })
            .then(json => dispatch(setAllProjects(json)))
            .then(()=> dispatch(setAuthenticationData(loggedInUser)))
            .catch(error => {
                console.error(error)
                return dispatch(failedToLoadProjects(error))
            });
    }
} 

и тест на:

const checkActionsWereDispatched = async (expectedActions, actionCreator) => {
    const store = mockStore(Map(
        {
        }),
    );
    store.dispatch(await actionCreator.apply()).then(() => {
        expect(store.getActions()).toEqual(expectedActions)
    })
}

it('should create SET_ALL_PROJECTS action when fetching projects', async () => {
    fetch
        .once(JSON.stringify([{ access_token: "12345" }]))
        .once(JSON.stringify({ name: "x" }))
    const expectedActions = [
        { type: "SET_ALL_PROJECTS", json: { name: "x" } },
    ]
    checkActionsWereDispatched(expectedActions, actions.loadAllProjects)
});

Как отмечалось выше, я думаю, что версия теста Spetastium легче читать, чем моя, и его статья здесь была очень полезна.

0 голосов
/ 27 июня 2018

Какое промежуточное ПО Redux вы используете для асинхронных операций?Убедитесь, что вы установили промежуточное программное обеспечение при создании хранилища для тестирования.

Поскольку я не вижу, чтобы в вашем коде выше я предполагал, что мы не используем это промежуточное программное обеспечение здесь.

Поскольку loadAllProjectsфункция более высокого порядка, я бы сделал это:

it('should create SET_ALL_PROJECTS action when fetching projects', (done) => {
    fetch
        .once(JSON.stringify([{ access_token: "12345" }]))
        .once(JSON.stringify({ name: "x" }))

    const expectedActions = [
        { type: "SET_ALL_PROJECTS", json: { name: "x" } },
    ]

    // Higher order function that returns a new function.
    const loadAllProjectsAsync = actions.loadAllProjects();

    // The function returned expects a dispatch from Redux as an argument.
    // It will do async work and when its done, it will call the provided dispatch.
    loadAllProjectsAsync(store.dispatch).then(() => {
       expect(store.getActions()).toEqual(expectedActions);
       done();
    })

});

Вам также нужно изменить свой код для loadAllProjects, чтобы внутренняя функция возвращала обещание:

export const loadAllProjects = () => {
return (dispatch) => {

    // You will need to return the promise in order for the test to be able to call .then() on it.
    return getHeadersWithToken()
        .then(applicationJsonHeaders => {
            const requestOptions = {
                method: 'GET',
                headers: applicationJsonHeaders,
            };
            return fetch(process.env.REACT_APP_PROJECTS_API_URL + "/projects", requestOptions)
                .then(parseResponseAndHandleErrors)
                .then(json => {
                    dispatch(setAllProjects(json))})
                .catch(error => {
                    console.error(error)
                    dispatch(failedToLoadProjects(error))
                });
        })
}}

Кроме того, как уже было сказаноВы должны сообщить шутку, когда тест завершен, если вы тестируете асинхронный материал.Сделайте это, позволив своему вызову it принять done в качестве параметра и вызвать его в качестве функции после того, как вы проверили результат в .then ()

Это было просто быстрое решение с моей стороны.Там может быть что-то, чего я пропускаю или какие-то ошибки в приведенном выше коде, но вы понимаете, в чем дело.

Дайте мне знать, если у вас есть дополнительные вопросы?

...