我想用以下方法测试单例类的行为:
public class SomeSingleton
{
private final static int DEFAULT_VALUE1 = ...;
private final static int DEFAULT_VALUE2 = ...;
private static SomeSingleton instance;
public static void init(int value1, int value2)
{
if (instance != null)
{
throw new IllegalStateException("SomeSingleton already initialized");
}
instance = new SomeSingleton(value1, value2);
}
public static getInstance()
{
if (instance == null)
{
init(DEFAULT_VALUE1, DEFAULT_VALUE2);
}
return instance;
}
}
然后我有一个包含多个测试方法的测试类,它会多次调用init
:
@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeSingleton.class)
public class SomeSingletonTest {
@Test
public void testGetInstanceSunnyDay()
{
[...]
SomeSingleton.init(...);
[...]
SomeSingleton.getInstance();
[...]
}
@Test
public void testGetInstanceRainyDay()
{
[...]
SomeSingleton.init(...); // IllegalStateException
[...]
SomeSingleton.getInstance();
[...]
}
}
当我这样做时,我总是在第二次测试中得到IllegalStateException
因为instance != null
。
如何在一个测试类中运行涉及init
的多个测试?
将testGetInstanceSunnyDay
和testGetInstanceRainyDay
放在两个不同的类中可以解决问题,但我想知道是否有更好的解决方案。
答案 0 :(得分:5)
基本上单身人士很难测试,正是因为这种事情。您可以添加clearStateForTesting
方法:
static void clearStateForTesting() {
instance = null;
}
...但是如果可能的话,我建议你首先避免使用单身模式。
另请注意,您的单例实现目前不是线程安全的。如果确实需要使用单例,那么实现效果要好得多。
答案 1 :(得分:2)
虽然我同意Jon的观点,但另一个选择是使用ReflectionTestUtils或反射来将instance
字段设置为null
。知道如果字段名称发生变化,这可能会很脆弱。
答案 2 :(得分:0)
鉴于它是Singleton,init
方法作为公共方法没有任何意义。设为private
并在单元测试中仅使用getInstance
。