Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在一个测试类中测试单例?_Java_Unit Testing_Junit_Singleton - Fatal编程技术网

Java 如何在一个测试类中测试单例?

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

我想用以下方法测试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)
    {
        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是旧代码库的一部分。不是我写的。现在,我只想捕获单元测试中遗留代码的行为。然后逐步完善应用程序的设计。