使用模拟内部模拟进行单元测试

时间:2017-03-17 14:17:34

标签: java unit-testing

我需要对一个对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();
}

2 个答案:

答案 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 DemeterSingle Responsibility Principle。在这种情况下,它意味着您的类本身执行太多逻辑,而不是接受构造函数中的某些处理器来执行实际工作。

如果您这样做,您可以单独,轻松地测试处理器,并测试整个过程。

答案 1 :(得分:1)

请不要使用模拟,因为完全没有必要,但正如您已经意识到的那样,将导致痛苦和脆弱的测试。

  

或者这是一种我应该使用Builders并实际构建真实对象的问题吗?

你甚至不需要一个Builder(虽然我推荐它们) - 只需使用一个真实的对象。使用真实对象将导致测试必须对重构更具弹性,将测试您的代码实际正在做什么,而不仅仅是您认为它是什么。

相关问题