【问题标题】:How to mock a private inner class如何模拟私有内部类
【发布时间】:2011-04-08 09:34:11
【问题描述】:

我有一个 spring 应用程序,我想在这样的控制器上创建一个单一测试。问题是 Wrapper 类是私有内部类,所以在测试中没有理解 Wrapper。是否可以在不更改控制器类的情况下使用 Mockito 模拟它。我可以使用 prepareData() 来获取对象的一个​​实例,但我不知道这是否可以用来模拟该对象。

谢谢

@Controller
public class Controller {

    private class Wrapper {
        private Object1 field1;
        private Object2 field2;
        private Object1 method1(){
           ...
        }
        private Object2 method1(){
           ...
        }
    }

    @ModelAttribute("data")
    public Wrapper prepareData() {
            return new Wrapper ();
}

    public String save(@ModelAttribute("data") Wrapper wrapper, BindingResult result, Model model){
        ...
    }
}

所以在我的测试中我会有这样的东西

@Test
public void usernameEmpty(){

    BindingResult result = Mockito.mock(BindingResult.class);
    Model model = Mockito.mock(Model.class);
    Wrapper data = //how to mock it
    when(data.method1()).then(new Foo1());
    when(data.method2()).then(new Foo2());
    String returned = controller.save(data, result, model);
    ....
}

【问题讨论】:

  • 我问你为什么要这样做?您最终可能会测试错误的代码。如果内部类具有依赖项(可能通过控制器获得?)模拟那些。等待?你的代码编译了吗?如果 Wrapper 是私有类,你可以将它用作公共方法的参数吗?
  • @Martinho Fernandes 我是测试新手。我只是想对 save 方法进行测试,所以我需要模拟 Wrapper 对象,以便在对其调用某些方法时定义返回对象。是的,控制器编译(测试没有,但这是问题 - 我不能在测试中使用 Wrapper 类)。也许有更好的方法来做到这一点。
  • Java 再次让我感到惊讶(负面的)。如果手头没有 Java 编译器,这让我无能为力:( 无论如何,即使允许,我认为拥有一个需要私有知识的公共方法不是一个好的设计。它破坏了封装。你打算怎么做在实际的真实代码中使用该方法?有可能吗?
  • @Martinho Fernandes 你说得对,我想我会把它改成公开的

标签: java unit-testing spring-mvc mocking mockito


【解决方案1】:

您的测试是针对方法的,但它测试的是整个类的行为。如果您的内部类是私有的,那么它是一个实现细节。测试不应该知道的东西。该内部类中有很多行为,您想独立测试它,也许您应该将其公开并与该类分开。

也许你会想:但是……有很多代码要测试(一个非常大的不可分割的东西),我不能测试一些更小的东西吗?嗯,是。测试驱动开发要求仅在您添加更多测试时进行最小实现并添加更多代码。因此,您从一些测试和最小实现开始,然后对它们进行进化,直到测试具有所有规范,代码具有所有实现。

所以不要担心私有内部类。测试你的班级合同!

【讨论】:

  • 祝你单元测试好运!它提供了很大的信心和在不(无意中)破坏事物的情况下改变的能力!
  • 这不是很好 - 这将是集成测试。你打破了测试驱动开发的主要原则之一——测试应该很简单!
  • 是的。但是TDD是一种开发方法:先写测试,再写代码。在这种情况下,OP 可能会获得另一种设计(更简单和更模块化),而不是获得私有内部类。在这种情况下,它只是测试已经存在的代码。说:我同意这不是一个简单的测试,但私有内部类不能从容器类中提取,所以虽然它不简单,但它不是集成测试恕我直言(无论如何,重要的部分是“测试”:)
  • 我不这么认为。示例:如果文件详细说明了某些信息,有时需要内部缓存,通常可以将其设置为私有内部类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多