如何从 Jmokit 1.49 版本模拟私有方法

Tus*_*ase 6 junit jmockit mocking

我正在使用 Junit 3.8.1 并将 Jmokit 更新到 1.49

我有一个项目,其中现有测试与 MockUp 一起呈现。私有方法被嘲笑。将 Jmockit jar 更新到 1.49 版本后出现错误如下

java.lang.IllegalArgumentException: Unsupported fake for private method
Run Code Online (Sandbox Code Playgroud)

我要测试的 Java 类是

public class Foo {

String aVar;

public Foo(String str) {
    aVar = str;
}

private void concatStr(String append) {
    aVar = aVar.concat(append);
}

public void doSomeTask() {
    concatStr("Test");
}
}
Run Code Online (Sandbox Code Playgroud)

测试类是

public class FooTest extends TestCase {
public FooTest(String testName) {
    super(testName);
}

public static Test suite() {
    return new TestSuite(FooTest.class);
}

public void test() {
    new MockUp<Foo>() {
        @Mock
        private void concatStr(String append) {
            Assert.assertEquals("Test", append);
        }
    };

    Foo foo = new Foo("demoString");
    foo.doSomeTask();
}
}
Run Code Online (Sandbox Code Playgroud)

在控制台上出现如下错误

[INFO] Running org.test.jmokitupdate.FooTest
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.028 s <<< FAILURE! - in 
org.test.jmokitupdate.FooTest
[ERROR] test(org.test.jmokitupdate.FooTest)  Time elapsed: 0.025 s  <<< ERROR!
java.lang.IllegalArgumentException: Unsupported fake for private method 
Foo#concatStr(Ljava/lang/String;)V found
    at mockit.internal.faking.FakedClassModifier.visitMethod(FakedClassModifier.java:96)
    at mockit.asm.methods.MethodReader.readMethodBody(MethodReader.java:118)
    at mockit.asm.methods.MethodReader.readMethod(MethodReader.java:75)
    at mockit.asm.methods.MethodReader.readMethods(MethodReader.java:62)
    at mockit.asm.classes.ClassReader.readFieldsAndMethods(ClassReader.java:196)
    at mockit.asm.classes.ClassReader.accept(ClassReader.java:89)
    at mockit.internal.faking.FakeClassSetup.modifyRealClass(FakeClassSetup.java:80)
    at mockit.internal.faking.FakeClassSetup.redefineMethods(FakeClassSetup.java:61)
    at mockit.MockUp.redefineClass(MockUp.java:114)
    at mockit.MockUp.<init>(MockUp.java:78)
    at org.test.jmokitupdate.FooTest$1.<init>(FooTest.java:31)
    at org.test.jmokitupdate.FooTest.test(FooTest.java:31)
Run Code Online (Sandbox Code Playgroud)

Jef*_*ett 8

JMockit 的早期版本允许模拟私有方法,老实说,我认为这是与其他模拟框架的一个出色的区别。遗憾的是,最近的版本已经消除了模拟私有的能力 - 在 1.45 中成为警告,在 1.47 中成为例外。

没有真正的官方解释,尽管假设私有方法应该如此简单,以至于不需要测试/模拟。推而广之,如果您尝试出于测试目的访问它,那么它不应该是私有的。人们(除了您之外)可能也想改变该行为,并且您出于测试目的访问它的需要强烈表明该方法应该是可访问的。使其受保护或包私有。FWIW,有像“@VisibleForTesting”这样的注释可以用来帮助表明意图。

所以你知道,1.47 还删除了“解封装”机制,这是我最喜欢的检查/设置私有数据的工具之一。当时我不得不转换,这很痛苦,因为它弄乱了我的测试代码,但事后看来,@Tested/@Injectable(替代品)要干净得多。正如维护者所指出的,JMockit 并不是一种获取私有资源的方式,还有其他框架可以做到这一点,并且没有必要做他们做得更好的工作。我切换到 Apache 的 commons-lang3 (FieldUtils/MethodUtils/etc),但还有其他框架