使用 JMockit 和 Java 8 获得测试通过和覆盖率报告的问题

Issues getting both tests passing and a coverage report with JMockit and Java 8

我 运行 遇到了很多问题,试图让它正常工作。我只是尝试 运行 一组基本测试并使用 JMockit 生成覆盖率报告。这是针对 class 的,目的只是确保我们可以 运行 它,所以我什至没有写测试,教授写了。在让 JMockit 工作时遇到很多问题之后,我现在通过了测试(使用模拟),但是如果我使用 JMockit 1.43,则不会生成覆盖率报告。如果我使用 1.38,所有测试都会失败,但我会得到覆盖率报告。我同时使用了 JDK 8 和 JDK 11,似乎没有给我任何不同的错误。我没有使用 Maven。根据教授的要求,我正在使用 Eclipse。测试是用 JUnit 5 编写的。

这是我的 VM 参数(针对 1.38,但我一直在更改的唯一内容是 1.43):

-javaagent:/path/to/jmockit-1.38.jar
-Djmockit-coverage-output=html
-Djmockit-coverage-metrics=line,path
-Dlog4j.configurationFile=./conf/log4j-file-config.xml 
-Djmockit-coverage-excludes=sun.jvmstat.*

同样,1.43 没有出现错误(只是没有生成覆盖率报告),但这是我在使用 1.38 时遇到的错误:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the class NestHost or NestMembers attribute
    at java.instrument/sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
    at java.instrument/sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:193)
    at mockit.internal.startup.Startup.redefineMethods(Startup.java:171)
    at mockit.internal.state.MockFixture.redefineClasses(MockFixture.java:165)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.applyClassRedefinition(BaseTypeRedefinition.java:238)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineClass(BaseTypeRedefinition.java:231)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineClassAndItsSuperClasses(BaseTypeRedefinition.java:202)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineMethodsAndConstructorsInTargetType(BaseTypeRedefinition.java:188)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineTargetClassAndCreateInstanceFactory(BaseTypeRedefinition.java:271)
    at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineType(BaseTypeRedefinition.java:70)
    at mockit.internal.expectations.mocking.TypeRedefinition.redefineType(TypeRedefinition.java:29)
    at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:82)
    at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:68)
    at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldTypes(FieldTypeRedefinitions.java:55)
    at mockit.internal.expectations.mocking.FieldTypeRedefinitions.(FieldTypeRedefinitions.java:34)
    at mockit.integration.internal.TestRunnerDecorator.handleMockFieldsForWholeTestClass(TestRunnerDecorator.java:153)
    at mockit.integration.junit5.JMockitExtension.postProcessTestInstance(JMockitExtension.java:55)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeTestInstancePostProcessors(ClassTestDescriptor.java:215)
    at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.executeAndMaskThrowable(JupiterTestDescriptor.java:141)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeTestInstancePostProcessors(ClassTestDescriptor.java:215)
    at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:195)
    at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:177)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
    at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
    at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeTestInstancePostProcessors(ClassTestDescriptor.java:214)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateAndPostProcessTestInstance(ClassTestDescriptor.java:196)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider[=12=](ClassTestDescriptor.java:185)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider(ClassTestDescriptor.java:189)
    at java.base/java.util.Optional.orElseGet(Optional.java:369)
    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider(ClassTestDescriptor.java:188)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:81)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:58)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.prepare(HierarchicalTestExecutor.java:89)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:74)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively(HierarchicalTestExecutor.java:120)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:177)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively(HierarchicalTestExecutor.java:120)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively(HierarchicalTestExecutor.java:120)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:177)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively(HierarchicalTestExecutor.java:120)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

切换到 Java9(教授使用的是什么,即使它不受支持)、jmockit-1.38 和这些 VM 参数并且它有效:

-Djdk.attach.allowAttachSelf
-Djmockit-coverage-metrics=line,path
-Djmockit-coverage-output=html
-Djmockit-coverage-srcDirs=src/main/java
-Dlog4j.configurationFile=./conf/log4j-file-config.xml 
-Djmockit-coverage-excludes=sun.jvmstat.*

仍然不确定如何使用 8 或 11(以及任一 jmockit 版本)让它工作。