Конечно, я мог бы написать что-то вроде не использовать синглтон, они злые, использовать Guice / Spring / что угодно но, во-первых, это не ответило бы на ваш вопрос, а во-вторых, вы иногда приходится иметь дело с синглтоном, например, при использовании устаревшего кода.
Итак, давайте не будем обсуждать хорошее или плохое в синглтоне (для этого есть еще один вопрос ), но давайте посмотрим, как с ними обращаться во время тестирования. Во-первых, давайте посмотрим на общую реализацию синглтона:
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
public String getFoo() {
return "bar";
}
}
Здесь есть две проблемы тестирования:
Конструктор является закрытым, поэтому мы не можем его расширять (и мы не можем контролировать создание экземпляров в тестах, но, в общем-то, в этом смысл синглетонов).
* * * * * * * * * * * * * * * * * * * * * getInstance
является статическим, поэтому трудно внедрить в код фальшивый объект вместо одноэлементного объекта , используя * .
Для фальшивых фреймворков, основанных на наследовании и полиморфизме, оба вопроса, очевидно, являются большими проблемами. Если у вас есть контроль над кодом, один из вариантов - сделать ваш синглтон «более тестируемым», добавив установщик, позволяющий настроить внутреннее поле, как описано в Научитесь прекращать беспокоиться и любить синглтон в этом случае даже не нужны насмешливые рамки). Если вы этого не сделаете, современные фреймворки, основанные на перехвате и концепциях АОП, позволяют преодолеть ранее упомянутые проблемы.
Например, Обработка вызовов статического метода показывает, как смоделировать синглтон, используя Ожидания JMockit .
Другой вариант - использовать PowerMock , расширение для Mockito или JMock, которое позволяет имитировать вещи, которые обычно не могут быть смоделированы, как статические, финальные, приватные или конструкторские методы. Также вы можете получить доступ к внутренним компонентам класса.