Различные экземпляры Singleton с тестами JUnit - PullRequest
22 голосов
/ 30 января 2010

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

Есть идеи о том, как это сделать?

Ответы [ 7 ]

12 голосов
/ 02 февраля 2010

Не используйте синглтон.

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

Вместо этого сделайте конструктор общедоступным и напишите тесты, используя новые экземпляры. В вашей реальной программе используйте getInstance() для получения канонического глобального экземпляра (или используйте контейнер IOC).

И помните, что синглтоны - это патологические лжецы .

Если вам все еще не нравится идея Singleton, вместо того, чтобы делать конструктор общедоступным, вы можете добавить публичный (и статический) фабричный метод для создания экземпляров способом, который не может быть использован случайно, например :

public static MyClass TEST_CreateInstance() {
  return new MyClass();
}
12 голосов
/ 30 января 2010

Я предполагаю, что в вашем одноэлементном классе есть личное статическое поле для хранения инициализированного экземпляра.

Если вы не хотите изменять свой код, вы можете определить метод разрыва, который запускается после каждого теста, и в этом методе вы устанавливаете для этого статического поля значение null через отражение, как видно здесь .

3 голосов
/ 30 января 2010

Вы можете добавить метод для уничтожения синглтона, например destroyMe (); где вы деинициализируете все и устанавливаете экземпляр синглтона на ноль.

  public void destroyMe(){
   this.instance = null;
   //-- other stuff to turn it off.
}

Я все же оставлю проблемы с синхронизацией;)

Но зачем вам нужно повторно инициализировать ваш синглтон для каждого теста? Он не должен отличаться в зависимости от концепции синглтона.

2 голосов
/ 18 марта 2011

Spring предоставляет аннотацию DirtiesContext для этого конкретного случая использования, где вам нужны новые экземпляры одноэлементных компонентов для каждого тестового случая. По сути, он создает новый контекст приложения для каждого testcase / testclass, к которому применена эта аннотация.

2 голосов
/ 15 февраля 2010

I настоятельно рекомендуем отойти от Singletons в качестве шаблона проектирования и использовать Singleton в качестве области действия (Dependency Injection). Это просто заставило бы вашу проблему уйти.

Но если вы застряли в мире синглетонов, у вас есть несколько вариантов в зависимости от того, тестируете ли вы синглтон или зависимость.

Если вы тестируете зависимый предмет, то можете смоделировать синглтон, используя PowerMock и JMockIt . Смотрите мой предыдущий пост о насмешливом Runtime.getRuntime для получения инструкций о том, как это сделать.

Если вы тестируете синглтон, вам нужно ослабить правила построения или назначить синглтону метод «Сброс».

1 голос
/ 30 января 2010

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

все еще, чтобы сначала получить тесты, которые вы можете сделать:


static setInstance(...){ //package visibility or in difficult cases you have to use public
  instance = ...;
}

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

0 голосов
/ 01 февраля 2010

Экземпляр Singleton должен быть передан в SUT самим тестом - таким образом, вы создаете singleton (и уничтожаете) для каждого теста. Внедрение IoC и Mocking Framework, таких как Mockito, сделало бы этот подход почти тривиальным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...