使用Mockito模拟方法

时间:2012-05-29 14:25:38

标签: unit-testing mockito

使用mockito模拟方法是否确保永远不会调用mocked方法?我有Main类,其中包含一些我想编写单元测试的代码,我有一个单元测试类MainTest,它包含Main类的单元测试。

例如:

来源类:

package abc;

public class Main {

    public int check1() {
        int num = 10;
        num = modify(num);
        return num;
    }

    public int modify(int num) {
        if (num % 10 == 0) return num / 10;
        return -1;
    }
}

Junit测试(使用mockito)

package abc;

import junit.framework.Assert;

import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;

public class MainTest {

    private static Main main;

    @BeforeClass
    public static void setUp() {
        main = Mockito.mock(Main.class);
        Mockito.when(main.modify(10)).thenReturn(5);
    }

    @Test
    public void testCheck1() {
        Test1 main1 = new Main();
        int num = main.check1();
        Assert.assertEquals(5, num);
    }
}

此测试失败。为什么呢?

3 个答案:

答案 0 :(得分:8)

<强> EDITED 因为您没有为check1()提供行为。 所有方法都被模拟,因此,如果没有提供行为,check1()将返回int的返回类型的默认值,即0。此外,check1()因为它被模拟甚至没有打电话给modify()

如果您正在尝试测试一个类,那么您永远不会模拟测试类。在极少数情况下,您可能需要Spy正在测试的课程。相反,你只是模仿合作者。

我猜你的例子是一个人为的(我希望)。但是,如果您正在编写和测试一个您认为要修改某个内部方法行为的类,我会看到两个可能的概率:

  1. 您可能需要将要模拟的方法的功能重构为协作者类。然后继续将这种行为模仿为合作者是有道理的。
  2. 您可能还需要修改API,以便传入将要更改的内容。在您的情况下,check1()会对其传递给modify()的值进行硬编码,这就是您尝试模拟modify()的原因。如果该值是check1()的参数或类Main中的可设置字段,则根本不需要使用模拟。

答案 1 :(得分:4)

测试问题是,您不使用新创建的main1对象。

如果你想改变被测系统(SUT)的行为,你通常会做这样的事情:

@Test
public void testCheck1() {
    Test1 main1 = new Main(){
        public int modify(int num) {
            return 5; // hard coded return value
        }
    };
    int num = main1.check1();
    Assert.assertEquals(5, num);
}

这将创建Main的子类,其中包含modify-method的新实现。 这是替换SUT中难以测试的方法的重要技术。您通常会使用它来避免昂贵的远程呼叫或类似的。

当然可以像这样使用Mockito间谍:

@Test
public void testCheck1() {
    Test1 main1 = spy(new Main());
    stub(main1.modify(10)).toReturn(5);

    int num = main1.check1();
    Assert.assertEquals(5, num);
}

答案 2 :(得分:0)

虽然我迟到了,但对某些人来说可能有用。刚刚添加到@VivaceVivo答案:使用间谍时请考虑doReturn | Answer | Throw()系列方法进行存根。有时,使用(对象)咒语间谍是不可能或不切实际的。更多信息here