2012-05-09 6 views
2

У меня есть класс фабрики, чтобы восстановить конфигурацию для моего приложения:Тест синглтон с JUnit

public class ConfigurationFactory { 
private static ConfigurationFactory configurationFactory = new ConfigurationFactory(); 

private Configuration configuration = null; 

public static ConfigurationFactory getConfigurationFactory() { 
     return configurationFactory; 
    } 

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

public Configuration getConfiguration(String path){...} 
public Configuration getConfiguration(String database){...} 

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

public void resetConfiguration() { 
this.configuration = null; 
} 

И я чувствую, что я буду гореть в аду разработчика для этого он :)

Мой вопрос: есть ли другой способ сделать это без добавления этого метода?

Примечание: Я видел this, и я не могу использовать какие-либо рамки DI, такие как Spring или Guice, руководство полагает, что добавление фреймворка сделает проект тяжеловесным, поскольку эта программа предназначена для запуска как демон на серверах.

+0

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

+0

Да, но как я мог его реорганизовать? Я имею в виду, что я потратил некоторое время на поиски наилучшего способа сделать это, и фабрика синглтона показалась хорошей моделью, она действительно делает работу в ясной форме. Единственная проблема, с которой я столкнулся, - это тесты, но я не хочу реорганизовывать все это только для установки теста jUnit ... –

+1

Я рассматриваю модульные тесты как показатель качества кода. Если я сталкиваюсь с чем-то непроверенным, я стараюсь реорганизовать этот фрагмент кода. Но, конечно, это ваш код, и если эта проблема проверки не беспокоит вас, сброс экземпляра в порядке. Вы, например, взглянули на шаблон дизайна абстрактного завода? Я думаю, что это должно быть более testable ... – zafarkhaja

ответ

0

Некоторые из вещей, которые я могу думать является

  1. Используйте насмешливые рамки, как Easymock или Mockito издеваться над ConfigurationFactory и использовать эти фиктивные объекты в других областях, требующих.

  2. Определите набор, определенный в классе ConfigurationFactory, и определите аннотацию как @TestPurpose и используйте это, чтобы переопределить одноэлементный объект из ваших модульных тестов. Аннотации означают, что это не должно использоваться во время потока приложения, и функция предназначена только для цели junit.

+0

один быстрый вопрос, вы хотите написать модульный тест для ConfigurationFactory или другого класса, который зависит от ConfigurationFactory. Если какой-то другой класс, то определенно вы можете попробовать насмешливые фреймворки. – raddykrish

+0

Нет, это просто проверка ConfigurationFactory. Тесты, например, загружают конфигурацию из файла, загружают из базы данных и т. Д. –

+0

Ahh..I видеть, тогда макет будет полезен в насмешек конфигураций. Если конструктор этого класса не выполняет задачу загрузки всех этих данных, вы можете определенно написать модульные тесты для этого класса. Вы можете возвращать mock-объекты для методов 'getConfiguration' и выполнять утверждения. – raddykrish

1

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

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

+0

Я не могу использовать guice, см. Мою заметку ... но спасибо! –

0

Если вы не хотите использовать предложенные фреймворки, вы все равно можете просто разделить 'src' и 'test-src' и использовать защищенный метод вместо общедоступного. Это не идеально, но предотвращает вызовы этого метода сброса, позволяя вам тестировать.

  • SRC/главная/myproject.myfactory.ConfigurationFactory
  • SRC/тест/myproject.myfactory.TestConfigurationFactory

-> в JUnit-класса используют @After или @AfterClass -методов к call reset

Если вам нужна фабрика в течение нескольких сценариев тестирования, вы также можете создать абстрактный класс BaseTest, который содержит метод @AfterClass для очистки таких синглетов.

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