2017-02-22 97 views
0

Я создаю приложение react-redux с использованием специального промежуточного программного обеспечения для сокращения. В определении моего проекта действие предоставляет только объект для определения типа действия и необходимых параметров для промежуточного программного обеспечения и редуктора. Все запросы ajax будут обрабатываться промежуточным программным обеспечением. Это жизненный цикл будет выглядеть так: действие -> промежуточное ПО (если действие перехвачено) -> редуктор -> магазинтестирование пользовательского промежуточного программного обеспечения redux, которое обрабатывает запрос ajax

Когда пользователь пытается войти в систему, операция над реагирующим компонентом вызовет действие, которое буду выглядеть следующим образом:

export function login(username, password) { 
    return { 
    type: 'LOGIN', 
    username: username, 
    password: password 
    } 
} 

export function authSucceed(username, isAdmin) { 
    return { 
    type: 'AUTHSUCCEED', 
    username: username, 
    isAdmin: isAdmin 
    } 
} 

export function authFail(text) { 
    return { 
    type: 'AUTHFAIL', 
    errorMessage: text 
    } 
} 

Затем промежуточный слой будет использовать параметры, передаваемые в действии, чтобы отправить запрос Ajax, который был бы так.

export function customedMiddleware(store) { 
    return next => action => { 
    if (action.type === 'LOGIN') { 
     axios.post(url + '/api/login', { 
     username: action.username, 
     password: action.password 
     }) 
     .then(res => { 
      if (res.status === 200) { 
      store.dispatch(actions.authSucceed(res.data.username, res.data.isAdmin)); 
      } else { 
      store.dispatch(actions.authFail(res.data)); 
      } 
     }) 
     .catch(error => console.log(error)); 
     } 
     return next(action); 
    }; 
    } 

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

export default function(state = false, action) { 
    switch(action.type) { 
    case 'AUTHSUCCEED': 
     return true; 
    case 'AUTHFAIL': 
     return false; 
    case 'LOGOUT': 
     return false; 
    } 
    return state; 
} 

Что здесь сделано в редукторе - это изменение состояния системы. Если состояние истинно, внешний интерфейс отобразит страницу информации. Если состояние ложно, внешний интерфейс останется на странице входа.

Мне нравится определение системы таким образом. Каждая часть MVC хорошо изолирована. Однако тестирование промежуточного программного обеспечения очень сложно. В настоящее время я тестирую этот путь:

it('should dispatch authSucceed if signup with correct info',() => { 
    nock('http://localhost:8080') 
    .post('/api/signup', { 
     username: 'bruce', 
     password: 'Gx1234' 
    }) 
    .reply(200, { 
     username: 'bruce', 
     isAdmin: false 
    }); 

    const createStoreWithMiddleware = applyMiddleware(customedMiddleware)(createStore); 
    const store = createStoreWithMiddleware(reducers); 
    const dispatch = sinon.spy(store, 'dispatch'); 

    store.dispatch(actions.login('bruce', 'Gx1234')); 
    setTimeout(() => { 
    expect(dispatch.calledWith({ 
     type: 'AUTHSUCCEED', 
     username: 'bruce', 
     isAdmin: false 
    })).to.be.true; 
    }, 100); 
}); 

Я отправляю логин. Затем запустите проверку правильности действия authSucceed и authFail в течение 100 мс. Этот метод работает, если выполняется только один тест. Если в последовательности выполняется более одного теста, они могут влиять друг на друга. Я должен настроить временную задержку setTimeout, чтобы она работала для всех случаев, которая составляет 10 мс. Мне это не удобно. Я не могу убедиться, что это просто работает для меня или для всех, поскольку абсолютное время связано с оборудованием. Я был бы очень признателен, если кто-нибудь может дать мне несколько советов о том, как протестировать это обычное промежуточное программное обеспечение.

+0

Что произойдет, если вы используете 'setTimeout (..., 0)'? – Lucas

+0

http://redux.js.org/docs/recipes/WritingTests.html#async-action-creators Вот хороший ресурс. Кроме того, почему бы не использовать redux-thunk? –

+0

фактически, комплектTimeout (..., 0) работы. –

ответ

0

Ваш код работает нормально, но вам не понадобится setTimeout с таким долгого времени, так как использование нока делает удаленный ответ на запрос ответа мгновенно. Проблема заключается в обещаниях enqueue microtasks, и они запускаются только после завершения макросаны (в вашем случае it()), в том же цикле событий.

Вот почему вам нужно setTimeout, чтобы поставить очередную макрозадачу, время не имеет значения. Я считаю, что setImmediate должен работать.