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

bz4sfanl  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(198)

假设我有一个这样的类:

public class MyClass {

    Dao dao;

    public String myMethod(Dao d) {

        dao = d;

        String result = dao.query();

        return result;
    } 
}

我想用mockito来测试它,所以我创建了一个mock对象,并调用了这个方法来测试:

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

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

new MyClass().myMethod(mock);

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

public class MyClass {

    Dao dao = new Dao();

    public String myMethod() {

        String result = dao.query();

        return result;
    } 
}

现在我不能把我的模拟作为一个参数传递,那么我该怎么测试我的方法呢?有人能举个例子吗?

y1aodyip

y1aodyip1#

从根本上说,你试图用一个替代的实现来替换一个私有字段,这意味着你违反了封装。你唯一的选择是重新构造类或方法,使其更好地设计用于测试。
评论中有很多简短的答案,所以我将它们汇总在这里(并添加几个我自己的)作为社区Wiki。* 如果您有任何替代方案,请随时添加到这里。*

重新构建类

  • 为有问题的字段创建setter,或者放宽字段的可见性。
  • 创建一个接受DAO的依赖注入重写或静态方法,并将公共示例方法委托给它。请测试更灵活的方法。
public String myMethod() { return myMethod(dao); }
String myMethod(Dao dao) { /* real implementation here */ }

注意,如果你把你的测试放在同一个Java包中(可能在一个单独的源代码树中),其中一些可以是包私有的。在所有情况下,好的名称和文档有助于让你的意图清晰。

违反封装

  • 使用反射设置类中的私有字段。(kinbiko-请参见answer
  • 使用PowerMockito将Dao构造函数替换为您选择的模拟。(Dave Newton
ryoqjall

ryoqjall2#

这个怎么样?

public class MyClassTest {

    MyClass myClass = new MyClass();
    Dao dao = Mockito.mock(Dao.class);

    public void testMyMethod() {

        Field field = myClass.getClass().getDeclaredField("dao");
        field.setAccessible(true);
        field.set(myClass, dao);
        //Do the test...
    } 
}

编辑:正如在注解中提到的,这里假设您没有更改dao字段的名称。然后获得所有的字段,Field[] fields = myClass.getClass().getDeclaredFields();,并迭代它们,获得Dao类型的字段,这可能是一个好主意。然后如上所述继续进行。这样您的测试就不再依赖于您的字段的名称了。

相关问题