Что тестируется
LanguageRedux.js
имеет следующий экспорт:
LanguageTypes
- карта типов действий
Creators
- карта действий создателей
INITIAL_STATE
- начальное состояние приложения
getLanguage
и setLanguage
- функции редуктора
reducer
- редуктор
Я рекомендую импортировать все с ожидаемыми идентификаторами, например:
import Creators, {
LanguageTypes,
INITIAL_STATE,
getLanguage,
setLanguage,
reducer
} from '../../../redux/LanguageRedux';
Примечание : похоже, что действие getLanguage
не нужно, поскольку оно ничего не делает для состояния (если приложение получает язык, оно должно просто прочитать его из состояния), но я буду оставьте это там, так как оно находится в коде вопроса.
LanguageTypes
LanguageTypes
- это просто карта типов действий и связанных с ними строковых значений:
it('should export the expected action types', () => {
expect(LanguageTypes).toEqual({
GET_LANGUAGE: 'GET_LANGUAGE',
SET_LANGUAGE: 'SET_LANGUAGE'
}); // Success!
});
Создатели
Creators
- карта создателей действий.
Каждый создатель действия - это чистая функция, которая генерирует объект действия на основе заданных параметров:
describe('Creators', () => {
describe('getLanguage', () => {
it('should return the expected action', () => {
expect(Creators.getLanguage()).toEqual({
type: LanguageTypes.GET_LANGUAGE
});
});
it('should ignore extra args', () => {
expect(Creators.getLanguage('extra arg')).toEqual({
type: LanguageTypes.GET_LANGUAGE
});
});
});
describe('setLanguage', () => {
it('should return the expected action when passed nothing', () => {
expect(Creators.setLanguage()).toEqual({
type: LanguageTypes.SET_LANGUAGE
}); // Success!
});
it('should return the expected action when passed a language', () => {
expect(Creators.setLanguage('en')).toEqual({
type: LanguageTypes.SET_LANGUAGE,
language: 'en'
}); // Success!
});
it('should ignore extra args', () => {
expect(Creators.setLanguage('es', 'extra arg')).toEqual({
type: LanguageTypes.SET_LANGUAGE,
language: 'es'
}); // Success!
});
});
});
INITIAL_STATE
INITIAL_STATE
- это просто объект начального состояния, с которого начинается приложение:
it('should set the initial state ', () => {
expect(INITIAL_STATE).toEqual({ language: "en" }); // Success!
});
Функции редуктора
getLanguage
и setLanguage
являются функциями-редукторами, то есть они являются чистыми функциями, которые возвращают новое состояние на основе существующего состояния и заданного им действия:
describe('reducers', () => {
describe('getLanguage', () => {
it('should do nothing (probably should not be an action)', () => {
expect(getLanguage(INITIAL_STATE, {})).toEqual(INITIAL_STATE); // Success!
});
it('should ignore extra args', () => {
expect(getLanguage(INITIAL_STATE, { extra: 'arg' })).toEqual(INITIAL_STATE); // Success!
});
});
describe('setLanguage', () => {
it('should set the language', () => {
expect(setLanguage(INITIAL_STATE, { language: 'es' })).toEqual({
language: 'es'
}); // Success!
});
it('should ignore extra args', () => {
expect(setLanguage(INITIAL_STATE, { language: 'fr', extra: 'arg' })).toEqual({
language: 'fr'
}); // Success!
});
});
});
Обратите внимание, что тестирование функций редуктора с помощью reduxsauce
даже проще, чем тестирование стандартных redux
редукторов, поскольку они будут только вызываться для действий, для которых они предназначены.
редуктор
reducer
является редукторным редуктором, и его задача - направить действия в соответствующую функцию редуктора и вернуть полученное состояние:
describe('reducer', () => {
it('should return initial state if passed nothing', () => {
expect(reducer()).toEqual(INITIAL_STATE); // Success!
});
it('should route GET_LANGUAGE to getLanguage', () => {
expect(reducer(INITIAL_STATE, Creators.getLanguage())).toEqual(INITIAL_STATE); // Success!
});
it('should route SET_LANGUAGE to setLanguage', () => {
expect(reducer(Immutable({ language: 'es' }), Creators.setLanguage('fr'))).toEqual({
language: 'fr'
}); // Success!
});
});
Примечание : существует несколько различных способов проверки reducer
. Вышеупомянутый подход передает состояние и действия полностью через функции редуктора. Он тщательный, но также имеет много общего с тестами функций редуктора, приведенными выше.
Самая основная альтернатива - это шпионить за createReducer
и просто проверить, что он был вызван с ожидаемым INITIAL_STATE
и объектом сопоставления.
Подход на полпути между этим и полным подходом, описанным выше, состоит в том, чтобы смоделировать функции редуктора, передать reducer
различные действия и убедиться, что была вызвана правильная функция редуктора. Вероятно, это идеальный подход, но трудно реализовать способ написания кода в настоящее время, поскольку createReducer
запускается, как только код импортируется и захватывает ссылки на локальные функции setLanguage
и getLanguage
. Если вы хотите использовать этот подход, то самый простой способ сделать это - переместить reducer
в его собственный модуль, чтобы можно было смоделировать функции редуктора перед импортом reducer
в ваш тестовый код.