2016-12-22 10 views
0

Я новичок в области редукции и программирования в целом, и у меня возникают проблемы с переворачиванием головы вокруг определенных концепций тестирования модулей.Тестирование async redux с вызовами сторонних API

У меня есть некоторые асинхронные действия в redux, которые включают вызовы стороннего API (из модуля узлов amazon-cognito-identity-js).

Я завернул внешний API-вызов в функцию обещания, и я вызываю эту функцию из «фактического» создателя действия. Поэтому для тестирования я просто хочу заглушить результат функции externalAWS(), чтобы проверить, правильно ли отправлены правильные действия.

Я использую утилизацию для моего промежуточного программного обеспечения.

import { AuthenticationDetails, 
     CognitoUser 
} from 'amazon-cognito-identity-js'; 

export function externalAWS(credentials) { 

    //This is required for the package 
    let authenticationDetails = new AuthenticationDetails(credentials); 

    let cognitoUser = new CognitoUser({ 
    //Construct the object accordingly 
    }) 

    return new Promise ((resolve, reject) => { 

    cognitoUser.authenticateUser(authenticationDetails, { 
     onSuccess: result => { 
     resolve(result); 
     }, 
     onFailure: error => { 
     reject(error) 
     } 
    }) 
    } 
} 

export function loginUser(credentials) { 

    //return function since it's async 
    return dispatch => { 

    //Kick off async process 
    dispatch(requestLogin()); 

    externalAWS(credentials) 
     .then((result) => { 
     dispatch(receiveLogin(result.getAccessToken().getJwtToken(), credentials.username)) 
     }) 
     .catch((error) => { 
     dispatch(failedLogin(error.message, etc)) 
     }) 
    } 
} 

У меня пока нет тестового кода, потому что я действительно не уверен, как подойти к этому. Все примеры связаны с издевательством HTTP-запроса, который, как я знаю, составляет , к чему это сводится, поэтому я должен проверять HTTP-запросы в своем браузере и издеваться над ними напрямую?

Это еще больше осложняется тем фактом, что второй аргумент authenticateUser не является даже обычным обратным вызовом, а объектом с обратными вызовами как его значениями.

Может ли кто-нибудь предложить какой-либо совет относительно того, правильно ли я намерен в модуле тестировать функцию асинхронной работы и как я должен подходить к ней? Спасибо.

Редактировать: Я тестирую в Jest.

Edit2: Заголовки запросов First POST request, Second POST request

Edit3: Разделить функции, стараясь изо всех сил, чтобы изолировать внешний API и создать что-то, что является "легко насмехаться/окурка состоянии. Но все еще проблема с тем, как правильно заглушить эту функцию.

ответ

0

Так я понял это в конце концов. Во-первых, мне пришлось потребовать() модуль в свой тестовый файл (в отличие от импорта ES6). Затем я удалил это обещание, так как он добавил слой сложности и объединил все в одну функцию, назовем его loginUser(). Это асинхронное действие reducex, которое отправляет одно действие при вызове, а затем действие успеха или отказа в зависимости от результата вызова API. См. Выше, как выглядит вызов API.

Тогда я написал тест следующим образом:

const CognitoSDK = require('/amazon-cognito-identity-js') 
const CognitoUser = CognitoSDK.CognitoUser 

//Set up the rest of the test 

describe('async actions', (() => { 
    it('should dispatch ACTION_1 and ACTION_2 on success', (() => { 
    let CognitoUser.authenticateUser = jest.fn((arg, callback) => { 
     callback.onSuccess(mockResult) 
    }) 
    store.dispatch(loginUser(mockData)) 
    expect(store.getActions()).toEqual([{ACTION_1}, {ACTION_2}]) 
    })) 
})) 

Поэтому в основном когда-то требует модуля, я дразнил его в Шутках и сделал макет реализации тоже, так что я мог бы получить доступ к OnSuccess функции обратного вызова объект.

0

Redux thunk дает вам возможность отправлять будущие действия в контексте основного действия, которое запускает процесс. Это основное действие - ваш твой боевик.

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

Тесты также должны учитывать то, что аргументы переданы вашим создателям действий, чтобы ваши редукторы могли быть проинформированы о результатах запроса и соответственно обновить хранилище.

Чтобы начать работу с тестированием вашего создателя действия thunk, вы хотите проверить, что три действия отправляются соответствующим образом в зависимости от того, успешно ли вход в систему или нет.

  1. requestLogin
  2. receiveLogin
  3. failedLogin

Вот некоторые тесты, которые я написал для вас, чтобы начать использовать Нок для перехвата запросов HTTP.

Тесты

import nock from 'nock'; 

const API_URL = 'https://cognito-idp.us-west-2.amazonaws.com/' 

const fakeCredentials = { 
    username: 'fakeUser' 
    token: '1234' 
} 

it('dispatches REQUEST_LOGIN and RECEIVE_LOGIN with credentials if the fetch response was successful',() => { 

    nock(API_URL) 
    .post() // insert post request here e.g - /loginuser 
    .reply(200, Promise.resolve({"token":"1234", "userName":"fakeUser"}) }) 

    return store.dispatch(loginUser(fakeCredentials)) 
    .then(() => { 
     const expectedActions = store.getActions(); 
     expect(expectedActions.length).toBe(2); 
     expect(expectedActions[0]).toEqual({type: 'REQUEST_LOGIN'}); 
     expect(expectedActions[1]).toEqual({type: 'RECEIVE_LOGIN', token: '1234', userName: 'fakeUser'}); 
    }) 
}); 

it('dispatches REQUEST_LOGIN and FAILED_LOGIN with err and username if the fetch response was unsuccessful',() => { 

    nock(API_URL) 
     .post() // insert post request here e.g - /loginuser 
     .reply(404, Promise.resolve({"error":"404", "userName":"fakeUser"})) 

    return store.dispatch(loginUser(fakeCredentials)) 
    .then(() => { 
     const expectedActions = store.getActions(); 
     expect(expectedActions.length).toBe(2); 
     expect(expectedActions[0]).toEqual({type: 'REQUEST_LOGIN'}); 
     expect(expectedActions[1]).toEqual({type: 'FAILED_LOGIN', err: '404', userName: 'fakeUser'}); 
    }) 
}); 
+0

Спасибо, это помогает объяснить идеи, лежащие в основе тестирования асинхронных действий. Тем не менее, мой тест по-прежнему терпит неудачу, поскольку исходная функция 'authenticateUser' все еще работает. Я знаю это, потому что он не работает с исключением из документов для этого API («Пользователь не найден», предположительно из «fakeUser»). –

+0

Кстати, насмехаясь над ответом, я тоже наименее знаком, поэтому я не знаю, как устранить проблему здесь. –

+0

Какой url запрашивается при вызове api? – therewillbecode

 Смежные вопросы

  • Нет связанных вопросов^_^