java - 使用 JMockit 模拟被测类的私有(private)方法

标签 java unit-testing junit mocking jmockit

我想模拟一个被测类的私有(private)方法,但是当方法被调用时,方法首先返回 false 两次,然后它应该返回 false。 这是我尝试过的代码。 这是正在测试的类

public class ClassToTest 
{
    public void methodToTest()
    {
        Integer integerInstance = new Integer(0);
        boolean returnValue= methodToMock(integerInstance);
        if(returnValue)
        {
            System.out.println("methodToMock returned true");
        }
        else
        {
            System.out.println("methodToMock returned true");
        }
        System.out.println();
    }
    private boolean methodToMock(int value)
    {
        return true;
    }
}

测试类

import org.junit.Test;
import static mockit.Deencapsulation.*;

import mockit.*;
public class TestAClass 
{
    @Tested ClassToTest classToTestInstance;
    @Test
    public void test1()
    {

        new NonStrictExpectations(classToTestInstance)
        {
            {
                invoke(classToTestInstance, "methodToMock", anyInt);
                returns(false);
                times = 2;

                invoke(classToTestInstance, "methodToMock", anyInt);
                returns(true);
                times = 1;

            }
        };

        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();

    }
}

我这样做是为了得到想要的结果

    final StringBuffer count = new StringBuffer("0");
    new NonStrictExpectations(classToTestInstance)
    {

        {
            invoke(classToTestInstance, "methodToMock", anyInt);
            result= new Delegate() 
            {
                boolean methodToMock(int value)
                {                   
                    count.replace(0, count.length(), Integer.valueOf(Integer.valueOf(count.toString())+1).toString());
                    if(Integer.valueOf(count.toString())==3)
                    {
                        return true;
                    }
                    return false;
                }
            };

        }
    };

最佳答案

使用期望(或 StrictExpectations)

结合使用 Expectations 和 Deencapsulation.invoke(),您可以部分模拟测试对象:

import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;

public class TestAClass
{
    public static class ClassToTest 
    {
        public void methodToTest()
        {
            boolean returnValue = methodToMock(0);
            System.out.println("methodToMock returned " + returnValue);
        }

        private boolean methodToMock(int value) { return true; }
    }

    @Tested ClassToTest classToTestInstance;

    @Test
    public void partiallyMockTestedClass() {
        new Expectations(classToTestInstance) {{
            invoke(classToTestInstance, "methodToMock", anyInt);
            result = false;
            times = 2;
        }};

        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
    }
}

上面的测试打印:

methodToMock returned false
methodToMock returned false
methodToMock returned true

当然,一般来说,我们应该避免模拟 private 方法。也就是说,我在实践中发现这样做有时是有用的,通常是当您有一个私有(private)方法执行一些重要的事情并且已经被另一个测试测试过时;在这种情况下,在第二次测试中模拟该私有(private)方法(针对不同的公共(public)方法或通过同一公共(public)方法的不同路径)可能比设置必要的输入/条件容易得多。

使用 NonStrictExpectations(在 JMockit 1.23 中弃用)

使用 NonStrictExpectations 编写测试同样容易(OP 最初的尝试没有成功,只是因为相同的非严格期望被记录两次,第二次记录覆盖了第一):

@Test
public void partiallyMockTestedClass() {
    new NonStrictExpectations(classToTestInstance) {{
        invoke(classToTestInstance, "methodToMock", anyInt);
        returns(false, false, true);
    }};

    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
}

使用委托(delegate)

如果需要更大的灵 active ,我们总是可以记录一个基于Delegate的结果:

@Test
public void partiallyMockTestedClass() {
    new NonStrictExpectations(classToTestInstance) {{
        invoke(classToTestInstance, "methodToMock", anyInt);

        result = new Delegate() {
           boolean delegate() {
               boolean nextValue = ...choose next return value somehow...
               return nextValue;
           }
        }
    }};

    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
}

关于java - 使用 JMockit 模拟被测类的私有(private)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24427685/

相关文章:

JavaFX 的东西不会引用

java - 开始使用 TestFx

unit-testing - 使用 UnderscoreJS 为 AngularJS 编写测试

maven - java.lang.OutOfMemoryError : PermGen with Jenkins and Maven

mysql - derby 和 hsqldb 中的 From_unixtime

java - 检测 ActiveMQ 主题的使用者的变化

java - 增加或减少一个角度以最短的方式到达另一个角度

java - Thymeleaf 数组元素连接

java - 错误: java: cannot find symbol symbol: class MockitoJUnitRunner

unit-testing - Autofixture 和 WebApi Controller