Java 如何在一个测试类中测试单例?
我想用以下方法测试singleton类的行为:Java 如何在一个测试类中测试单例?,java,unit-testing,junit,singleton,Java,Unit Testing,Junit,Singleton,我想用以下方法测试singleton类的行为: 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
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!=空
如何在一个测试类中运行多个涉及init
的测试
将
TestGetInstanceSunyday
和testGetInstanceRainyDay
放在两个单独的类中可以解决问题,但我想知道是否有更好的解决方案。从根本上讲,单例很难测试,正是因为这样的事情。您可以添加clearStateForTesting
方法:
static void clearStateForTesting() {
instance = null;
}
。。。但是如果可能的话,我建议你首先要避免单身模式
还要注意,您的单例实现目前不是线程安全的。如果您真的需要使用单例,则有明显更好的实现。尽管我同意Jon的观点,但另一种选择是使用或反射,将
实例
字段设置为null
。知道如果字段名更改,这可能很脆弱。鉴于它是一个单例,因此init
方法作为公共方法毫无意义。在单元测试中使用private
,并且只使用getInstance
。另一个类似的选项是使用反射将instance
字段设置为null
@JohnB:事实上,我尽量避免在测试中使用反射。同意。在使用脆弱的反射和向类中添加仅用于测试的方法之间进行折衷是很糟糕的。不管怎样都不太好。干杯。@JohnB从我的主观观点来看,在这种情况下,反思是最好的选择。请将您的评论作为答案提交,我将接受。@DmitriPisarenko:如果更改私有字段名,是否希望测试中断?对我来说这听起来很脆弱。但是,嘿,首先我会尽量避免使用单例:)请注意,“仅用于测试的呈现”方法的存在让任何阅读代码的人都非常清楚测试此代码所需的内容。如果其他使用singleton的代码需要测试不同的配置,那么它的可重用性也会更高。您认为singleton在这里提供了什么好处,比如说,一个不可变的类不会?singleton是旧代码库的一部分。不是我写的。现在,我只想捕获单元测试中遗留代码的行为。然后逐步完善应用程序的设计。