以下是 Mockito 单元测试框架的引用:
不要模拟值对象
为什么有人会想要这样做呢?
因为实例化对象太痛苦了!? => 无效
原因。如果创造新的装置太困难,那就是一个迹象
代码可能需要一些认真的重构。另一种方法是创建
价值对象的构建者——有一些工具可以实现这一点,包括
IDE 插件、Lombok 等。一个人也可以创造出有意义的东西
测试类路径中的工厂方法。
还有另一句话来自here http://www.mockobjects.com/2007/04/test-smell-everything-is-mocked.html:
为简单的值对象编写模拟没有多大意义
(无论如何应该是不可变的),只需创建一个实例并使用
它。不值得创建一个接口/实现对来控制返回哪些时间值,只需创建具有适当值的实例并使用它们即可。当一个类不值得嘲笑时,有一些启发式的方法。首先,它只有访问器或简单的方法来作用于它所持有的值,它没有任何有趣的行为。其次,除了 VideoImpl 或某些此类模糊术语之外,您无法为该类想出任何有意义的名称。
这似乎是哑值对象仅保存值而没有其他内容的合理原因,但是当您有一个引用实体和其他值对象的 ValueObject 时,事情会变得更加复杂。
假设我有 Person 和 Pet 对象,它们是实体,而 Relationship(所有者、医生等)是两个人之间的 ValueObject,并且有一个 ReasoningType,它也是一个 Value 对象。所以,关系基本上是:
class Relationship {
private Person person;
private Pet pet;
private RelationshipType type;
}
现在,假设我有一个带有 isOwnerRelationship、isDoctorRelationship 等谓词的类。基本上谓词很简单
关系->关系.isOwner(); //委托关系Type.isOwner()
现在,我想测试谓词,我有两个选择:
模拟关系
public void testIsOwner() {
Relationship rel = mock(Relationship.class);
when(rel.isOwner()).thenReturn(true);
assertTrue(RelationshipPredicates.isOwner(rel));
}
不要嘲笑关系
public void testIsOwner() {
Person person = PersonBuilder.newPerson();
Pet pet = PetBuilder.newDogPet();
RelationshipType type = RelationshipTypes.ownerType();
Relationship rel = new Relationship(person, pet, type);
assertTrue(RelationshipPredicates.isOwner(rel));
}
当然,这个例子过于简化,因为对于一个人,你可能需要提供地址,对于宠物,你可能必须提供 BreedType,无论如何,即你可能需要提供的实体和值对象的传递图可能非常巨大。当然,您可以模拟实体,但假设您在关系内部有更多 ValueObjects 的 ValueObjects。即使您有出色的构建器,您也必须提供原始 ValueObject 的每个部分,即使单元测试仅测试它的单个方面。
在谓词测试中,如果谓词关心调用对象的一个特定方法或它们的组合,为什么我应该关心完整的对象构造?
或者是这样的值对象不能被视为simple并且规则不适用?