最近我们的系统中出现了一个错误,该错误是由于忘记在复制构造函数中分配新添加的类属性而引起的。
例如:
public class MyClass {
private Long companyId;
private Long classId;
private Double value; <= newly added
public MyClass(MyClass myClass) {
this.setCompanyId(myClass.getCompanyId());
this.setClassId(myClass.getClassId());
this.setValue(myClass.getValue()); <= we forget this line
}
我想编写一个单元测试,保证在添加新属性时捕获丢失的副本分配。我应该如何进行?
我会通过反思来做到这一点。
MyClass
的实例。 (一)getClass().getDeclaredFields()
来完成。MyClass
的空白实例。 (B)IMO,有三种方法可以解决这个问题
@Builder(toBuilder=true)
class Foo {
int x;
...
}
Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().build(); // copy
null
,0
,) 0.0
、false
、'\0'
)import java.util.Objects;
// other imports
public class FooTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Test
public void testCopyConstructor_shouldCopyAllFields() {
// should be instantiated with non-default values
Foo original = new Foo();
original.setSimilarity(0.1);
// set your fields here
Foo copied = new Foo(original);
// You can use reflections if you don't want to add Jackson as your dependency
Map<String, Object> originalMap = OBJECT_MAPPER.convertValue(original, new TypeReference<HashMap<String, Object>>(){});
for (Object value : originalMap.values()) {
// if we add new fields and forget to update this test, this test should fail
assertTrue(value != null && !Objects.equals(value, 0.0)
&& !Objects.equals(value, 0) && !Objects.equals(value, false)
&& !Objects.equals(value, '\0'), "");
}
Map<String, Object> resultingMap = OBJECT_MAPPER.convertValue(copied, new TypeReference<HashMap<String, Object>>(){});
for (Map.Entry<String, Object> entry : resultingMap.entrySet()) {
Object expectedValue = originalMap.get(entry.getKey());
assertEquals(entry.getValue(), expectedValue);
}
}
}
import java.util.Objects;
// other imports
public class FooTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Test
public void testCopyConstructor_shouldCopyAllFields() {
EasyRandom generator = new EasyRandom();
for (int i = 0; i < 4; i++){ // you can do it multiple times if you're unsure
Person person = generator.nextObject(Person.class);
Person copied = new Person(person);
// or if you afraid of forgetting to update your .equals() method,
// just convert both of them to hashmaps (using jackson)
// and compare the hashmaps
assertEquals(copied, person);
}
}
}