当前位置: 首页 > 知识库问答 >
问题:

使用Eclipse(EclEmma/JaCoCo)代码覆盖运行时,ByteBuddy重置失败

马坚白
2023-03-14

我在单元测试中使用ByteBuddy重新定义类。我在每次测试后重置类,以确保测试之间没有串扰。

只要在EclipseIDE中运行测试,或者使用maven命令行运行,ByteBuddy就可以正常工作。但如果它在Eclipse中运行并覆盖,重置该类会导致以下异常:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)

下面是一个示例测试,它通过默认的JUnit运行程序,但在Eclipse中使用代码覆盖运行时失败。下面是失败的完整堆栈跟踪。

我使用的是ByteBuddy版本1.8.22和EclEmmaJava代码覆盖包版本3.1.0.201804041601。

我假设这个问题是由于ByteBuddy类修改和EclEmma代码检测之间的冲突造成的。是否有替代方法来恢复类定义,以解决这个问题?

不在保险范围内:

import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.implementation.FixedValue;

public class ByteBuddyEclEmmaTest {

    @Test
    public void recreateEclEmmaByteBuddyResetIssue() throws Exception {

        ByteBuddyAgent.install();

        ByteBuddy byteBuddy = new ByteBuddy();
        ClassReloadingStrategy classReloadingStrategy = ClassReloadingStrategy.fromInstalledAgent();

        byteBuddy
                .redefine(X.class)
                .method(named("getValue")).intercept(FixedValue.value("faked value"))
                .make()
                .load(X.class.getClassLoader(), classReloadingStrategy);

        X x = new X();
        assertThat(x.getValue()).isEqualTo("faked value");

        classReloadingStrategy.reset(X.class);

        assertThat(x.getValue()).isEqualTo("real value");
    }

    public class X {

        public String getValue() {

            return "real value";
        }
    }
}

堆栈跟踪:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
    at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
    at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
    at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:261)
    at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.reset(ClassReloadingStrategy.java:279)
    at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.reset(ClassReloadingStrategy.java:209)
    at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.reset(ClassReloadingStrategy.java:195)
    at ByteBuddyEclEmmaTest.recreateEclEmmaByteBuddyResetIssue(ByteBuddyEclEmmaTest.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

共有1个答案

厉熠彤
2023-03-14

我发现我的问题是由老版本的ByteBuddy引起的。我在Mockito的项目中加入了1.6.14版。当我显式引入ByteBuddy版本1.8.22时,测试成功运行,包括覆盖和不覆盖。

 类似资料:
  • 我是jUnit的新手,我试图加深我对它的了解。我在网上搜索了一下,但没有找到任何可以解决几个疑问的东西。 这是代码: 这是jUnit4测试用例: TestCase运行正常,没有任何问题,但我有两个简单的问题/问题: 1) 只测试方法的正确功能是正确的,还是应该同时测试值和/或任何特定异常? 2) 当我用EclEmma运行代码覆盖率时,它给了我75%的代码覆盖率,因为测试用例没有测试类的构造函数。测

  • 我正在尝试使用JaCoCo-javaagent传递VM参数来获得代码覆盖率 -Java agent:/test/jaco co/jaco agent . jar = dest file =/test/jaco co/jaco co . exec,includes=com。*,append=true 我能在jacoco中获得一些价值。执行文件,但无法获取覆盖率报告。我怎样才能把jacoco转化成。执

  • 我有一个maven项目(link),我想在上面运行代码覆盖率。 我在主项目pom文件上运行了命令,但没有生成报告。相反,我得到的警告是 有人能建议我如何用这个pom文件生成代码覆盖率报告吗。我正在使用apache-maven-3.3。9和testNG。

  • 我正在使用Android Studio 1.2。2和Gradle插件1.2。3. 我正在尝试生成代码覆盖率报告,而不运行,只运行。我希望避免需要连接设备或模拟器,这样我就可以加快Jenkins服务器上的构建速度。 到目前为止,我所能做的最好的事情就是在报告中包含单元测试执行数据,如下所述:Android Studio中的Jacoco代码覆盖。这对于显示所有测试的结果很有用,但是目前我只想运行单元测

  • 我的代码运行在具有单独JVM的单独虚拟机上。我想在此虚拟机上以tcpserver模式设置JaCoCo代理以收集覆盖率数据。然后,我将在我的maven项目中以tcpclient模式设置JaCoCo代理,以连接到上面提到的VM并获取覆盖率数据。 问题是代理不收集任何覆盖数据。在中创建了覆盖率数据文件,但该文件为空。 下面是代理选项:-Java agent:/usr/xx/plugins/org . j

  • 我在声纳中的代码覆盖率显示为0%,这不是真的,因为我有单元测试。 格拉德尔 当我打开inside然后我可以看到成功的单元测试。 我在Jenkins环境中运行作为