如何从 Jmockit 1.49 版本模拟私有方法
How to mock private methods from Jmokit 1.49 version
我正在使用 Junit 3.8.1 并将 Jmokit 更新到 1.49
我有一个项目,其中现有测试与 MockUp 一起出现。嘲笑私有方法。将 Jmockit jar 更新到 1.49 版本后出现如下错误
java.lang.IllegalArgumentException: Unsupported fake for private method
我要测试的Javaclass是
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");
}
}
并且测试 class 是
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();
}
}
控制台出现如下错误
[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.<init>(FooTest.java:31)
at org.test.jmokitupdate.FooTest.test(FooTest.java:31)
早期版本的 JMockit 允许模拟私有方法,老实说,我认为这是与其他模拟框架的绝妙区别。可悲的是,最近的版本已经消除了模拟私有的能力——在 1.45 中成为警告,在 1.47 中成为例外。
没有真正的官方解释,虽然假设是私有方法应该很简单,他们不需要 testing/mocking。推而广之,如果您出于测试目的而尝试访问它,那么它不应该是私有的。人们(除了你)可能也想改变行为,并且你出于测试目的访问它的需要强烈建议该方法应该是可访问的。使其受保护或包私有。 FWIW,有像“@VisibleForTesting”这样的注释可以用来帮助表明意图。
所以你知道,1.47 还删除了“解封装”机制,这是我最喜欢的 inspecting/setting 私有数据工具之一。当时我不得不转换很痛苦,因为它乱丢了我的测试代码,但事后看来,@Tested/@Injectable(替代品)更干净。正如维护者所指出的那样,JMockit 并不是一种获取私有的方式,还有其他框架可以做到这一点,并且在完成他们做得更好的工作时没有任何意义。我切换到 Apache 的 commons-lang3 (FieldUtils/MethodUtils/etc),但其他框架存在
我正在使用 Junit 3.8.1 并将 Jmokit 更新到 1.49
我有一个项目,其中现有测试与 MockUp 一起出现。嘲笑私有方法。将 Jmockit jar 更新到 1.49 版本后出现如下错误
java.lang.IllegalArgumentException: Unsupported fake for private method
我要测试的Javaclass是
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");
}
}
并且测试 class 是
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();
}
}
控制台出现如下错误
[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.<init>(FooTest.java:31)
at org.test.jmokitupdate.FooTest.test(FooTest.java:31)
早期版本的 JMockit 允许模拟私有方法,老实说,我认为这是与其他模拟框架的绝妙区别。可悲的是,最近的版本已经消除了模拟私有的能力——在 1.45 中成为警告,在 1.47 中成为例外。
没有真正的官方解释,虽然假设是私有方法应该很简单,他们不需要 testing/mocking。推而广之,如果您出于测试目的而尝试访问它,那么它不应该是私有的。人们(除了你)可能也想改变行为,并且你出于测试目的访问它的需要强烈建议该方法应该是可访问的。使其受保护或包私有。 FWIW,有像“@VisibleForTesting”这样的注释可以用来帮助表明意图。
所以你知道,1.47 还删除了“解封装”机制,这是我最喜欢的 inspecting/setting 私有数据工具之一。当时我不得不转换很痛苦,因为它乱丢了我的测试代码,但事后看来,@Tested/@Injectable(替代品)更干净。正如维护者所指出的那样,JMockit 并不是一种获取私有的方式,还有其他框架可以做到这一点,并且在完成他们做得更好的工作时没有任何意义。我切换到 Apache 的 commons-lang3 (FieldUtils/MethodUtils/etc),但其他框架存在