首页 文章

使用Mockito模拟方法

提问于
浏览
1

使用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

    EDITED 因为您没有为 check1() 提供行为 . 所有方法都被模拟,所以在没有提供行为的情况下, check1() 返回int的返回类型的默认值,即0 . 此外, check1() 因为它被模拟甚至不能调用 modify() .

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

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

    • 您可能需要将要模拟的方法的功能重构为协作者类 . 然后继续将这种行为模仿为合作者是有道理的 .

    • 您可能还需要修改API,以便传入将要更改的内容 . 在你的情况下, check1() 硬编码它传递给 modify() 的值,这就是你试图模拟 modify() 的原因 . 相反,如果该值是 check1() 的参数或类 Main 中的可设置字段,那么甚至根本不需要使用模拟 .

  • 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 Spy :

    @Test
    public void testCheck1() {
        Test1 main1 = spy(new Main());
        stub(main1.modify(10)).toReturn(5);
    
        int num = main1.check1();
        Assert.assertEquals(5, num);
    }
    
  • 8

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

相关问题