我需要对一个对X类型的对象起作用的特定方法进行单元测试.X对象几乎没有像String,int等常规字段,但它也有一个类型为Y的列表。这个Y类型也很复杂。为了使我的问题更加困难,让我们说Y型有另一个Z型列表。
理想情况下,我需要模拟对象X,但要告诉它在内部注入另一个类型为Y的模拟,这也应该向自身注入另一个模拟Z(到Y)。我该怎么做?
如果我有这么多级别的模拟,我应该如何避免在调用他们的方法时写出这些模拟实际应该返回的20个规范?
或者这是一种我应该使用Builders并实际构建真实对象的问题吗?
非常感谢, 鲍勃。
编辑: 我只是一个示例用法代码:
public String produceImportantStringOfImportantData(ObjectX x) throws ParseException {
StringBuilder textResult = new StringBuilder();
List<ObjectY> listOfY = x.getListOfY();
if (listOfY.isValid()) {
for (ObjectY y : listOfY) {
for (ObjectZ z : y.getListOfZ()) {
textResult.append("<font color='green'>").append(z.getField2).append("</font>").append(": ").append(z.getSomething())
.append(" Label : ").append(z.getParentComponent.getField()))
.append(" some important labels: ").append(z.getField()))
.append(" some important labels ").append(y.getAnotherField))
.append(" different, important label: ").append(y.getField()))
.append("<br/>");
}
}
}
return textResult.toString();
}
答案 0 :(得分:5)
假设您使用的是Mockito之类的模拟框架,您可以这样做:
X mockX = Mockito.mock(X.class);
Y mockX = Mockito.mock(Y.class);
Z mockX = Mockito.mock(Z.class);
Mockito.when(mockY.getZ()).thenReturn(mockZ);
Mockito.when(mockX.getY()).thenReturn(mockY);
如果这太深(你提到了20个规格),这可能表示你违反了Law of Demeter或Single Responsibility Principle。在这种情况下,它意味着您的类本身执行太多逻辑,而不是接受构造函数中的某些处理器来执行实际工作。
如果您这样做,您可以单独,轻松地测试处理器,并测试整个过程。
答案 1 :(得分:1)
请不要使用模拟,因为完全没有必要,但正如您已经意识到的那样,将导致痛苦和脆弱的测试。
或者这是一种我应该使用Builders并实际构建真实对象的问题吗?
你甚至不需要一个Builder(虽然我推荐它们) - 只需使用一个真实的对象。使用真实对象将导致测试必须对重构更具弹性,将测试您的代码实际正在做什么,而不仅仅是您认为它是什么。