【问题标题】:Jmockit Expectations/Verifications for calls to private methods when testing a public method?测试公共方法时调用私有方法的 Jmockit 期望/验证?
【发布时间】:2014-10-02 20:05:15
【问题描述】:

任何人都可以建议是否可以使用期望/验证来测试私有方法被称为正确的次数/正确的参数。

被测类已被模拟 - 覆盖了一个私有方法。

正在测试一个调用多个私有方法的公共方法。

我想知道是否可以验证对公共方法执行时将调用的其他私有方法的调用?

对被测代码/类的一些想法;

public class UnderTest {

    public void methodPublic(arg 1){
        .....
        methodPrivate1(var1);
        ....
        methodPrivate2(var2);
    }

    private void methodPrivate1(var1){
        //do stuff
    }

    private void methodPrivate2(var1){
        //do stuff
    }

}

在我的测试用例中

@Test
public void stateBasedTestMethod()
{
    UnderTest underTest;

    new MockUp<UnderTest>() {
        @Mock(invocations = 1)
        private void methodPrivate2(var1) {
            //do nothing in the mocked case
        }
    };

    underTest = new UnderTest();
    underTest.methodPublic(arg1);

    new Verifications() {{
        // Is there a way to test that methodPrivate1 has been called-once/with-expected-arguments
    }};
}

根据 Rogério 的回答进行了编辑。 我正在使用 jmockit 1.12 并且验证失败,因为使用提供的解决方案的方法调用该方法两次,正如我从 JMockit 文档中所想的那样。

故障跟踪; mockit.internal.UnexpectedInvocation:预计恰好 1 次调用 MyHelperTest$1#method3...,但被调用了 2 次​​strong>

包括我为此使用的完整代码。 如上所述 - 我的目标是模拟一种不做任何事情的私有方法。 并确保我可以验证另一个私有方法只被调用一次。

提前致谢,如果 Jmockit 可以做到这一点,希望能更好地理解。

测试代码。

public class MyHelperTest {

    @Test
    public void testHelper(@Mocked final MyDependent myDependent) {

        final MyHelper myHelper;

        new MockUp<MyHelper>() {

            @Mock(invocations = 1)
            private void method3(MyDependent myTable) {
                System.out.println("In Mocked Method");
                //do nothing in the mocked case
            }

        };

        myHelper = new MyHelper();

        myHelper.method1(myDependent);

        new Verifications() {{ 
            invoke(myHelper, "method2", myDependent); times = 1; 
        }};
    }

}

正在测试的类。

public class MyHelper {

    public void method1(MyDependent myDependent){
        method2(myDependent);
    }

    private void method2(MyDependent myDependent) {
        myDependent.setValue(1);
        method3(myDependent);
    }

    private void method3(MyDependent myDependent) {
        myDependent.setValue(2);
    }

}

依赖类

public class MyDependent {

    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

}

【问题讨论】:

    标签: jmockit


    【解决方案1】:

    这是可能的,但不建议模拟 private 方法。

    使用 Expectations API:

    @Tested @Mocked MyHelper myHelper;
    
    @Test
    public void testHelper(@Mocked final MyDependent myDependent)
    {
        new NonStrictExpectations() {{ invoke(myHelper, "method3", myDependent); }};
    
        myHelper.method1(myDependent);
    
        new Verifications() {{ invoke(myHelper, "method2", myDependent); times = 1; }};
    }
    

    ...invoke(...) 方法是从类mockit.Deencapsulation 静态导入的。

    【讨论】:

    • 感谢您的回复。建议的解决方案不会检查调用是否发生在私有方法上。相反,在“methodPrivate1”上进行了另一次调用——通过测试确认。从 mockit.Deencapsulation.invoke(Object, String, Object...) “使用给定参数从给定类调用不可访问(例如私有)实例方法。”我试图确定;测试公共方法时是否可以检查私有方法的调用(时间和参数)。关于模拟私有方法,这不是为了避免在测试期间写入数据库。
    • 我的示例测试应该适用于 JMockit 1.12;如果您使用的是旧版本,那么测试不会那么简单(@Tested + @Mocked 在同一字段上是一个新功能)。它应该检查对私有方法的调用,是的。
    • 请参阅上面对原始问题的编辑以响应您的反馈。提前致谢。
    • 上面答案中的更新测试是您想要的(在 JMockit 1.12 上测试)。
    【解决方案2】:

    我注意到,如果您要验证的方法未被模拟,则当执行 Expectations 或 Verifications 实例中的静态块时,代码会调用您尝试标记为预期或验证的方法。 这可能解释了您所看到的额外调用。

    一个建议:如果您已经在使用 MockUp 模拟类(并因此创建了一个匿名子类)以便您可以覆盖私有方法,为什么不将被覆盖的私有方法的访问权限更改为受保护或公共?然后,您可以对其创建期望或验证。

    您还可以提供一个公共字段“public int counter=0;”并让您的覆盖方法增加计数器。然后你可以在测试完成后对其使用断言。

    【讨论】:

    • 我不想更改访问权限,因为这些方法不打算在课堂之外使用。它们是辅助方法,仅对类有意义。
    • 你没有理解我的建议。我没有说更改您班级中方法的访问权限。我说在匿名子类中覆盖你的方法,并给它公共或受保护的访问权限。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2013-03-13
    相关资源
    最近更新 更多