1

使用 mockito 模拟方法是否确保永远不会调用模拟方法?我有 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);
    }
}

这个测试失败了。为什么?

4

3 回答 3

8

已编辑 因为您没有为check1(). 所有方法都会被模拟,因此如果您不提供行为,check1()则返回 int 的返回类型的默认值,即 0。此外,check1()由于它被模拟,因此甚至无法调用modify().

如果你想测试一个类,你永远不会模拟被测类。在极少数情况下,您可能需要监视正在测试的类。相反,您只嘲笑合作者。

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

  1. 您可能需要将要模拟的方法的功能重构为协作者类。然后,作为合作者继续嘲笑这种行为是有意义的。
  2. 您可能还需要修改 API,以便您可以传递将要更改的内容。在你的情况下,check1()硬编码它传递给的值modify(),这就是你试图模拟的原因modify()。相反,如果该值是check1()class 的参数或可设置字段Main,那么甚至根本不需要使用模拟。
于 2012-05-29T14:31:29.627 回答
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 的子类,其中包含修改方法的新实现。这是替换 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);
}
于 2012-05-29T15:08:36.043 回答
0

虽然我迟到了,但它可能对某些人有用。只是添加到@VivaceVivo 答案:使用间谍时,请考虑 doReturn|Answer|Throw() 存根方法系列。有时使用 when(Object) 来存根间谍是不可能或不切实际的。更多信息在这里

于 2016-09-08T20:32:47.067 回答