假设我正在测试一些涉及此类的代码:
import java.math.BigInteger;
import java.util.HashSet;
public class MyClass {
static int someStaticField = 5;
static BigInteger anotherStaticField = BigInteger.ONE;
static HashSet<Integer> mutableStaticField = new HashSet<Integer>();
}
您可以使用 Java 的反射功能以编程方式重置所有静态字段。在开始测试之前,需要存储所有初始值,然后在运行每个测试之前重置这些值。JUnit具有并为此而工作的注释。下面是一个简单的示例:@BeforeClass
@Before
import static org.junit.Assert.*;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Map;
import java.util.HashMap;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class MyTest extends Object {
static Class<?> staticClass = MyClass.class;
static Map<Field,Object> defaultFieldVals = new HashMap<Field,Object>();
static Object tryClone(Object v) throws Exception {
if (v instanceof Cloneable) {
return v.getClass().getMethod("clone").invoke(v);
}
return v;
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
Field[] allFields = staticClass.getDeclaredFields();
try {
for (Field field : allFields) {
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
Object value = tryClone(field.get(null));
defaultFieldVals.put(field, value);
}
}
}
catch (IllegalAccessException e) {
System.err.println(e);
System.exit(1);
}
}
@AfterClass
public static void tearDownAfterClass() {
defaultFieldVals = null;
}
@Before
public void setUp() throws Exception {
// Reset all static fields
for (Map.Entry<Field, Object> entry : defaultFieldVals.entrySet()) {
Field field = entry.getKey();
Object value = entry.getValue();
Class<?> type = field.getType();
// Primitive types
if (type == Integer.TYPE) {
field.setInt(null, (Integer) value);
}
// ... all other primitive types need to be handled similarly
// All object types
else {
field.set(null, tryClone(value));
}
}
}
private void testBody() {
assertTrue(MyClass.someStaticField == 5);
assertTrue(MyClass.anotherStaticField == BigInteger.ONE);
assertTrue(MyClass.mutableStaticField.isEmpty());
MyClass.someStaticField++;
MyClass.anotherStaticField = BigInteger.TEN;
MyClass.mutableStaticField.add(1);
assertTrue(MyClass.someStaticField == 6);
assertTrue(MyClass.anotherStaticField.equals(BigInteger.TEN));
assertTrue(MyClass.mutableStaticField.contains(1));
}
@Test
public void test1() {
testBody();
}
@Test
public void test2() {
testBody();
}
}
正如我在 中的注释中指出的那样,您需要使用类似的代码处理其余的基元类型来处理 s。所有包装类都有一个字段(例如 和 ),您可以像 检查一样。如果字段的类型不是基元类型(包括基元数组)之一,则它是一个,可以作为泛型处理。setUp()
int
TYPE
Double.TYPE
Character.TYPE
Integer.TYPE
Object
Object
可能需要调整代码来处理 、 和 字段,但您应该能够从文档中了解如何执行此操作。final
private
protected
祝您的旧代码好运!
编辑:
我忘了提一下,如果存储在其中一个静态字段中的初始值发生了突变,那么简单地缓存它并恢复它不会起作用,因为它只会重新分配突变的对象。我还假设您将能够扩展此代码以使用静态类数组而不是单个类。
编辑:
我添加了对对象的检查,以处理示例中的情况。显然,它并不完美,但希望这将涵盖您将遇到的大多数情况。希望边缘情况很少,手动重置它们(即将重置代码添加到方法中)不会太痛苦。Cloneable
HashMap
setUp()