【问题标题】:Mock class in class under test待测类中的模拟类
【发布时间】:2013-07-19 09:52:17
【问题描述】:

如何在我正在测试的班级中使用 Mockito 模拟其他班级?

例如:

MyClass.java

class MyClass {
    public boolean performAnything() {
        AnythingPerformerClass clazz = new AnythingPerformerClass();
        return clazz.doSomething();        
    }
}

AnythingPerformerClass.java

class AnythingPerformerClass {
    public boolean doSomething() {
        //very very complex logic
        return result;
    }
}

并测试:

@Test
public void testPerformAnything() throws Exception {
    MyClass clazz = new MyClass();
    Assert.assertTrue(clazz.performAnything());
}

我可以欺骗AnythingPerformerClass 以从AnythingPerformerClass 中排除不必要的逻辑吗?我可以覆盖doSomething() 方法以简单返回truefalse

为什么我指定 Mockito,因为我需要它来使用 Robolectric 进行 Android 测试。

【问题讨论】:

  • 为什么要为每个方法调用实例化一个类的实例?这看起来严重矫枉过正

标签: java unit-testing junit4 mockito robolectric


【解决方案1】:

您可以重构MyClass,使其使用dependency injection。与其创建AnythingPerformerClass 实例,不如将类的实例传递给MyClass 的构造函数,如下所示:

class MyClass {

   private final AnythingPerformerClass clazz;

   MyClass(AnythingPerformerClass clazz) {
      this.clazz = clazz;
   }

   public boolean performAnything() {         
     return clazz.doSomething();        
   }
}

然后你可以在单元测试中传入模拟实现

@Test
public void testPerformAnything() throws Exception {
   AnythingPerformerClass mockedPerformer = Mockito.mock(AnythingPerformerClass.class);
   MyClass clazz = new MyClass(mockedPerformer);
   ...
}

或者,如果您的 AnythingPerformerClass 包含状态,那么您可以将 AnythingPerformerClassBuilder 传递给构造函数。

【讨论】:

  • 根据Mockito docs,原语boolean的默认返回值为false,所以这个测试用例失败了。
  • 好吧,我省略了模拟方法调用的步骤。 OP 说“我可以覆盖 doSomething() 方法以简单地返回真或假吗?”所以我认为我不应该限制代码。
【解决方案2】:

按照目前的情况(在方法中声明和实例化 AnythingPerformerClass,仅使用 Mockito 来模拟 AnythingPerformerClass 是不可能的。

如果可能,将AnythingPerformerClass 的声明和实例化都移到类级别:声明AnythingPerformerClass 类型的实例变量并由构造函数实例化它。

这样,您可以更轻松地在测试期间注入 AnythingPerformerClass 的模拟,并指定其行为。例如:

when(anythingPerformerClassMock.doSomething()).thenReturn(true);

或测试错误处理:

when(anythingPerformerClassMock.doSomething()).thenTrow(new NullPointerException());

【讨论】:

    【解决方案3】:

    您可以在 Mockito 中设置要返回的内容。

    when(mock.method()).thenReturn(someValue)
    

    【讨论】:

    • 不起作用,即使您在同一个测试中模拟两个类,mockito 也无法推断出外部类应该使用模拟对象。
    猜你喜欢
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多