2016-09-22 2 views
2

У меня есть rootReducer, который импортирует все отдельные восстановители, как так:испытаний, были ли все редукторы были импортированы в rootReducer

import { combineReducers } from 'redux'; 
import departments from './departments'; 
import indicators from './indicators'; 
import versions from './versions'; 
import projects from './projects'; 

// combine all reducers to a single reducer, state will be linked to a reducer via the key used here 
const rootReducer = combineReducers({ 
    versions, 
    departments, 
    indicators, 
    projects, 
}); 

export default rootReducer; 

Поскольку это важно для этого редуктора импортировать все, я думаю, что это имеет смысл, чтобы проверить, является ли все импортированные редукторы в ./src/reducers. Единственный метод, который я могу думать, будет использовать fs для проверки количества файлов в ./src/reducers (без index или rootReducer) и проверьте, содержит ли в нем rootReducer много редукторов.

Кажется, это уродливое испытание и немного хрупкое. Но все же было бы очень приятно получить уведомление о неудачной проверке, когда вы забудете включить редуктор. Какой был бы лучший способ проверить, были ли импортированы все редукторы?

ответ

1

Я слышал, откуда вы родом, но я не думаю, что вы хотите иметь дело с этой проблемой в своих тестах. По мере роста вашего приложения вы, скорее всего, захотите получить более глубокое дерево редуктора. Например. ваш редуктор projects может состоять из нескольких субредукторов, и вам нужно будет управлять тем, какие редукторы нужно импортировать из того места. Тест файловой системы станет все более хрупким. В общем, импорт и файловые структуры - это детали реализации вашего проекта, и вы хотите проверить поведение своего проекта.

Но отсутствие немедленной обратной связи о невозможности подключения редуктора имеет смысл. Я бы попытался справиться с этим на уровне сборки.Предполагая, что вы используете Webpack, можете узнать, может ли this plugin решить вашу проблему. Он обнаруживает неиспользованный экспорт. Добавьте его в свои плагины

new UnusedFilesWebpackPlugin({ pattern: 'src/reducers/**' }) 

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

+0

А, это отличное решение! Я думаю, что ваше различие между реализацией и поведением имеет большой смысл. Легче рассуждать о том, что именно нужно тестировать. Благодаря! – vkjb38sjhbv98h4jgvx98hah3fef

0

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

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

  1. Импорт функция называется combineReducers
  2. Импорт каждый из переходников, которые я хочу быть включены
  3. вызов combineReducers и передать объект содержащий каждый из переходников, которые я хочу быть включен
  4. Экспорта результата вызова combineReducers

Похоже, вы беспокоитесь только ж ith # 3, что зависит от правильности # 1 и # 2. Если вы хотите проверить, что combineReducers вызывается с аргументами, которые вы ожидаете, почему бы не заглушить эту функцию и не утвердить это поведение?

Вы можете использовать SinonJS для stubcombineReducers, и после того как вы require() корневой редуктор, вы можете утверждать, что combineReducers называли когда-то, и что она была вызвана с объектом, который содержит ключи и значения, которые вы ожидаете. Вот как я мог бы сделать что-то подобное (с использованием mocha тестовой базы и chai для утверждений):

import * as Redux from 'redux'; 
import sinon from 'sinon'; 
import chai, {expect} from 'chai'; 
import sinonChai from 'sinon-chai'; 

import departments from './departments'; 
import indicators from './indicators'; 
import versions from './versions'; 
import projects from './projects'; 

chai.use(sinonChai); 

describe('Root Reducer',() => { 
    before(() => { 
     sinon.stub(Redux, 'combineReducers'); 
     require('./path/to/your/root/reducer'); 
    }); 

    after(() => { 
     Redux.combineReducers.restore(); 
    }); 

    it('should use all of the created reducers',() => { 
     const expectedReducers = { 
      versions, 
      departments, 
      indicators, 
      projects 
     }; 

     expect(Redux.combineReducers).to.have.callCount(1); 
     expect(Redux.combineReducers).to.be.calledWith(expectedReducers); 
    }); 
}); 

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

+2

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

+0

Конечно, но если разработчик должен был случайно удалить его, это поймало бы его. Это довольно простой процесс добавления еще одного редуктора и обновления этого теста вместе с ним. –

+0

Действительно, удаление этого редуктора было бы уловлено этим тестом. Но я думаю, что наиболее распространенным случаем было бы забыть добавить его. Я думаю, что моя цель - это не то, что в конечном итоге принадлежит моим модульным тестам. Как предположил @MichaelParker, это будет больше дома в процессе сборки. Спасибо за Ваш ответ! – vkjb38sjhbv98h4jgvx98hah3fef

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