在测试类中模拟被测试类中的类

30

我该如何在正在测试的类中使用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 来排除其中不必要的逻辑吗?我可以重写 doSomething() 方法,让它简单地返回 true 或者 false 吗?

为什么我需要使用 Mockito?因为我需要在 Robolectric 中进行 Android 测试。


1
为什么每次方法调用都要实例化一个类的实例?这看起来严重过度了。 - fge
3个回答

34

你可以重构 MyClass,使用依赖注入。而不是让它创建一个 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包含状态(state),那么你可以将一个AnythingPerformerClassBuilder传递给构造函数。


根据Mockito文档所述,原始类型boolean的默认返回值将为false,因此此测试用例失败。 - mthmulders
好的,我省略了模拟方法调用的步骤。原帖中说:“我能否重写doSomething()方法,使其简单地返回true或false?”因此,我认为我不应该限制代码。 - cyon

3
目前情况是(声明和实例化AnythingPerformerClass在方法内),仅使用Mockito无法对AnythingPerformerClass进行模拟。
如果可能,请将AnythingPerformerClass的声明和实例化移至类级别:声明一个类型为AnythingPerformerClass的实例变量,并通过构造函数实例化。
这样,在测试期间,您可以更轻松地注入AnythingPerformerClass的模拟,并指定其行为。例如:
when(anythingPerformerClassMock.doSomething()).thenReturn(true);

或者进行错误处理测试:

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

0

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

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

2
即使您在同一个测试中模拟了两个类,Mockito也无法推断外部类应该使用模拟对象,因此它仍然无法正常工作。 - Talha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接