java - 基于枚举的单例实现和单元测试,将状态保留为枚举的副作用

标签 java junit enums singleton

正如许多人所说,单例是不好的,它是一种“反模式”。幸运的是,无论是否幸运,我使用的一些代码确实拥有它,并且它不会在不久的将来消失。所以我的问题如下。

具有状态的单例:

import java.util.HashMap;
import java.util.Map;

public enum Singleton {
    INSTANCE;

    private final Map<String, String> _mapper = new HashMap<String, String>();

    public String getValue(String key) {
        return _mapper.get(key);
    }

    public void addEntry(String key, String val) {
        _mapper.put(key, val);
    }

    public String removeKey(String key) {
        return _mapper.remove(key);
    }
}

非常愚蠢的测试,没有考虑到在测试运行中保留单例实例状态:

import org.junit.Assert;
import org.junit.Test;

public class SingletonTest {

    public static final String KEY_1 = "key_1";

    @Test public void testOne() {
        Singleton.INSTANCE.addEntry(KEY_1, "val_1");
        Singleton.INSTANCE.addEntry("key_2", "val_2");
    }

    @Test public void testTwo() {
        Assert.assertNull(Singleton.INSTANCE.getValue(KEY_1));
    }
}

如何在测试运行之间清理状态?可以用 JUnit Runners 来完成吗?

对象的实际状态更加复杂,并通过构造函数初始化。我正在寻找类似的东西:http://powermock.googlecode.com/svn/docs/powermock-1.3.5/apidocs/org/powermock/core/classloader/annotations/PrepareForTest.html

最佳答案

您可以使用用@After修饰的方法,该方法将在执行每个测试后执行。在此方法中,您可以清除枚举中 map 的状态:

@After
public void clear() {
    Singleton.INSTANCE.removeKey(KEY_1);
    Singleton.INSTANCE.removeKey("key_2");
    //and on and on...
}

当然,更好的方法是在 enum 中使用 clear 方法,该方法将清除 map 的值,因此您的 @ 的正文After 方法会变得更短:

@After
public void clear() {
    //assuming you can create such method
    Singleton.INSTANCE.clearEntries();
}

关于java - 基于枚举的单例实现和单元测试,将状态保留为枚举的副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23206112/

相关文章:

java - 使 Spring Boot JSON 枚举反序列化严格,因此它不会默默地将无效值转换为 null

java - x 在数组堆栈中。我不知道为什么我的代码不起作用。因为即使我给出 ArrayStack 中的 x 它也会返回 false

Java - 本地类和泛型,为什么编译器警告?

java - org.hibernate.StaleStateException : Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

java - 如何通过流中的三元条件返回值?

enums - 如何获取枚举中元素(变体)的数量作为常量值?

java - 如何使用 Jersey Client 2.2.x 取消挂起的异步请求并取消注册调用回调?

java - 将base64异常字符串编码和解码为sql server 2008 r2

javax.validation.ValidationException : HV000028: Unexpected exception during isValid in Test

java - JUnit 类别不会运行某些测试