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



>假设我有这样的类:

public class MyClass {
    Dao dao;
    public String myMethod(Dao d) {
        dao = d;
        String result = dao.query();
        return result;
    } 
}

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

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;
    } 
}

现在我不能通过我的模拟作为参数,那么我将如何测试我的方法呢?有人可以举个例子吗?

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

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

重构类

  • 为相关字段创建二传手,或放宽字段的可见性。

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

    public String myMethod() { return myMethod(dao); }
    String myMethod(Dao dao) { /* real implementation here */ }
    
  • 添加构造函数重载或静态工厂方法,用于替换私有字段以进行测试。

  • 完全构造用于依赖注入的类。(Sotirios Delimanolis, EJK(

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

违反封装

  • 使用反射在类中设置私有字段。 (金比科 - 见答案(
  • 使用 PowerMockito 将Dao构造函数替换为您选择的模拟。(戴夫·牛顿(
这个

怎么样?

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 类型的字段可能是个好主意。然后按上述方式进行。这样,您的测试就不再依赖于字段的名称。

相关内容

  • 没有找到相关文章

最新更新