当我们无法将模拟对象传递给类的实例时如何使用 Mockito

2022-01-14 00:00:00 mockito java

假设我有这样的课程:

public class MyClass {

    Dao dao;

    public String myMethod(Dao d) {

        dao = d;

        String result = dao.query();

        return result;
    } 
}

我想用 mockito 测试它.所以我创建了一个模拟对象并以这种方式调用该方法进行测试:

I want to test it with mockito. So I create a mock object and I call the method to test in that way:

Dao mock = Mockito.mock(Dao.class);

Mockito.when(mock.myMethod()).thenReturn("ok");

new MyClass().myMethod(mock);

但是,假设我有一个这样的课程:

But, suppose instead I have a class like that:

public class MyClass {

    Dao dao = new Dao();

    public String myMethod() {

        String result = dao.query();

        return result;
    } 
}

现在我无法将我的模拟作为参数传递,那么我将如何测试我的方法?有人可以举个例子吗?

Now I cannot pass my mock as an argument, so how I gonna test my method? Can someone show an example?

推荐答案

从根本上说,您试图用替代实现替换私有字段,这意味着您违反了封装.您唯一的其他选择是重组类或方法,使其更适合测试.

Fundamentally, you're trying to replace a private field with an alternative implementation, which means you'd violate encapsulation. Your only other option is to restructure the class or method, to make it better-designed for testing.

评论中有很多简短的答案,所以我在这里将它们汇总(并添加我自己的几个)作为社区 Wiki.如果您有任何替代方案,请随时在此处添加.

There are a lot of short answers in the comments, so I'm aggregating them here (and adding a couple of my own) as Community Wiki. If you have any alternatives, please feel free to add them here.

  • 为相关字段创建一个 setter,或放宽该字段的可见性.

  • Create a setter for the field in question, or relax the field's visibility.

创建一个采用 DAO 的依赖注入覆盖或静态方法,并将公共实例方法委托给它.改为测试更灵活的方法.

Create a dependency-injecting override or static method that takes a DAO, and make the public instance method delegate to it. Test the more-flexible method instead.

public String myMethod() { return myMethod(dao); }
String myMethod(Dao dao) { /* real implementation here */ }

  • 添加构造函数重载或静态工厂方法来替换私有字段以进行测试.

  • Add a constructor overload or static factory method that replaces private fields for the sake of testing.

    完全构建依赖注入的类.(Sotirios Delimanolis, EJK)

    Fully structure the class for dependency injection. (Sotirios Delimanolis, EJK)

    请注意,如果您将测试放在同一个 Java 包中(可能在单独的源代码树中),其中一些可以是包私有的以进行测试.在任何情况下,良好的名称和文档都有助于明确您的意图.

    Note that some of these can be package-private for testing, if you put your tests in the same Java package (possibly in a separate source tree). In all cases, good names and documentation are helpful to make your intentions clear.

    • 使用反射在类中设置私有字段.(kinbiko - 请参阅 answer)
    • 使用 PowerMockito 替换 Dao 构造函数与您选择的模拟.(戴夫·牛顿)
    • Use reflection to set private fields in the class. (kinbiko - see answer)
    • Use PowerMockito to replace the Dao constructor with a mock of your choice. (Dave Newton)
  • 相关文章