Ответ
Для проверки однократной инициализации Singleton в тестах я использую несколько подходов, в зависимости от реализации паттерна.
1. Проверка ссылочной идентичности:
@Test
public void getInstance_ShouldReturnSameObject() {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
assertSame("Оба вызова должны возвращать один и тот же объект",
instance1, instance2);
}
2. Проверка через рефлексию (если нужно убедиться в однократном вызове конструктора):
@Test
public void constructor_ShouldBeCalledOnlyOnce() throws Exception {
// Сброс инстанса перед тестом (если есть такая возможность)
resetSingletonInstance();
// Первый вызов
Singleton instance1 = Singleton.getInstance();
// Попытка создать второй экземпляр через рефлексию
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
assertThrows(IllegalStateException.class, () -> {
Singleton instance2 = constructor.newInstance();
}, "Конструктор должен запрещать создание второго экземпляра");
}
3. Для потокобезопасных реализаций (Double-Checked Locking):
@Test
public void getInstance_ThreadSafe_ShouldReturnSameObject() throws InterruptedException {
final int threadCount = 10;
final CountDownLatch latch = new CountDownLatch(threadCount);
final Set<Singleton> instances = Collections.synchronizedSet(new HashSet<>());
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
instances.add(Singleton.getInstance());
latch.countDown();
}).start();
}
latch.await(5, TimeUnit.SECONDS);
assertEquals(1, instances.size(), "Все потоки должны получить один и тот же экземпляр");
}
Ключевые моменты тестирования Singleton:
- Проверка, что повторные вызовы
getInstance()возвращают тот же объект - Для ленивой инициализации — проверка, что объект создается только при первом вызове
- Для потокобезопасных реализаций — тестирование в многопоточной среде
- Проверка сериализации/десериализации (если Singleton реализует
Serializable) - Использование мок-фреймворков для изоляции тестов, если Singleton имеет сложные зависимости