繁体   English   中英

为什么我的 Mockito-inline JUnit 测试在运行 Ant 时会崩溃,并在 IntelliJ IDEA 中成功?

[英]Why do my Mockito-inline JUnit tests crash when run through Ant, and succeed in IntelliJ IDEA?

由于各种原因,我已经开始使用 Mockito 在我的单元测试中模拟一些类,并且随着我的开发,我得到了一切工作。 完成更改后,我推送到我们的构建服务器,发现通过 Ant 运行时单元测试被破坏。 我已经能够在一个简单的精简案例中重现这一点,其中我使用 Mockito 来测试模拟 static 方法的 class 的依赖关系。 下面我粘贴了源文件、测试文件、Ant 脚本和描述我正在使用的每个库的版本的 Ivy 依赖项文件(此时所有这些都是最新的),然后是详细错误 I看到了

但是,如果我在一个目录中创建这几个文件(使用src/com/example下的两个类和tests/com/example下的单元测试并将其作为 IntelliJ IDEA 项目打开,使用所有相同的依赖项(包括 JUnit)并运行所有测试,它成功了。与标准模块模板的唯一变化是指定JDK路径和Java级别为1.8。这是让它如此令人费解的部分原因。对于它的价值,Ant是否从Intelli内部调用都一样IDEA 的内置 Ant 集成,或者单独在命令行上。

商务舱.java

package com.example;

public class BusinessClass {
    public String returnString() {
        StaticDependency.DoSomething();
        return "Answer";
    }
}

静态依赖.java

package com.example;

public class StaticDependency {
    public static void DoSomething() {
        throw new RuntimeException("Real code causes side effects I'm isolating from");
    }
}

商务类Test.java

package com.example;

import org.junit.Test;
import org.mockito.MockedStatic;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mockStatic;

public class BusinessClassTest {
    @Test
    public void returnString() {
        final BusinessClass classUnderTest = new BusinessClass();

        try (final MockedStatic<StaticDependency> ignored = mockStatic(StaticDependency.class)) {
            assertEquals("Answer", classUnderTest.returnString());
        }
    }
}

ivy.xml

<ivy-module version="2.0">
  <info organisation="com.example" module="MockitoTest"/>
  <dependencies>
    <dependency org="junit" name="junit" rev="4.13.2"/>

    <!-- Mockito and dependencies -->
    <dependency org="org.mockito" name="mockito-inline" rev="4.2.0"/>
    <dependency org="net.bytebuddy" name="byte-buddy-dep" rev="1.12.6"/>
    <dependency org="org.objenesis" name="objenesis" rev="3.2"/>
  </dependencies>
</ivy-module>

build.xml

<project default="all" xmlns:ivy="antlib:org.apache.ivy.ant">

  <property name="lib" location="Lib"/>
  <property name="src" location="src"/>
  <property name="tests" location="tests"/>
  <property name="build-test" location="build-test"/>
  <property name="build" location="build"/>

  <path id="build.classpath">
    <fileset dir="${lib}">
      <include name="**/*.jar"/>
    </fileset>
  </path>

  <target name="all" depends="clean, resolve, compile, test"/>

  <target name="clean">
    <delete dir="${build}"/>
    <delete dir="${build-test}"/>
    <delete dir="${lib}"/>
  </target>

  <target name="resolve" description="Download dependencies">
    <ivy:resolve file="ivy.xml"/>
    <mkdir dir="${lib}"/>
    <ivy:retrieve pattern="${lib}/[artifact]-[type].[ext]"/>
  </target>

  <target name="compile" description="Compile the source code">
    <mkdir dir="${build}"/>
    <javac destdir="${build}">
      <src path="${src}"/>
      <classpath refid="build.classpath"/>
    </javac>

    <mkdir dir="${build-test}"/>
    <javac destdir="${build-test}">
      <src path="${src}"/>
      <src path="${tests}"/>
      <classpath refid="build.classpath"/>
    </javac>
  </target>

  <target name="test" depends="compile" description="Run all unit tests">
    <junit>
      <classpath>
        <path refid="build.classpath"/>
        <path path="${build-test}"/>
      </classpath>
      <formatter type="plain" usefile="false"/>

      <test name="com.example.BusinessClassTest" />
    </junit>
  </target>
</project>

JUnit output

Testsuite: com.example.BusinessClassTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.889 sec

Testcase: returnString took 0.779 sec
    Caused an ERROR
Could not modify all classes [class com.example.StaticDependency]
org.mockito.exceptions.base.MockitoException: Could not modify all classes [class com.example.StaticDependency]
    at com.example.BusinessClassTest.returnString(Unknown Source)
Caused by: java.lang.IllegalStateException: 
Byte Buddy could not instrument all classes within the mock's type hierarchy

This problem should never occur for javac-compiled classes. This problem has been observed for classes that are:
 - Compiled by older versions of scalac
 - Classes that are part of the Android distribution
    at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:280)
    at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.mockClassStatic(InlineBytecodeGenerator.java:221)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClassStatic(TypeCachingBytecodeGenerator.java:63)
    at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createStaticMock(InlineDelegateByteBuddyMockMaker.java:560)
    at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.createStaticMock(InlineByteBuddyMockMaker.java:83)
    at org.mockito.internal.util.MockUtil.createStaticMock(MockUtil.java:147)
    at org.mockito.internal.MockitoCore.mockStatic(MockitoCore.java:142)
    at org.mockito.Mockito.mockStatic(Mockito.java:2164)
    at org.mockito.Mockito.mockStatic(Mockito.java:2101)
Caused by: java.lang.AbstractMethodError: org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper.wrap(Lnet/bytebuddy/description/type/TypeDescription;Lorg/objectweb/asm/ClassVisitor;Lnet/bytebuddy/implementation/Implementation$Context;Lnet/bytebuddy/pool/TypePool;Lnet/bytebuddy/description/field/FieldList;Lnet/bytebuddy/description/method/MethodList;II)Lorg/objectweb/asm/ClassVisitor;
    at net.bytebuddy.asm.AsmVisitorWrapper$Compound.wrap(AsmVisitorWrapper.java:746)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor.visit(TypeWriter.java:4906)
    at org.objectweb.asm.ClassReader.accept(ClassReader.java:569)
    at org.objectweb.asm.ClassReader.accept(ClassReader.java:424)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:3951)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2213)
    at net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.make(RedefinitionDynamicTypeBuilder.java:224)
    at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:123)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3661)
    at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.transform(InlineBytecodeGenerator.java:394)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
    at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
    at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
    at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:276)

事实证明我的问题是我的ivy.xml文件中适得其反的byte-buddy-dep依赖。 正如@temp-droidGitHub 问题中指出的那样,我在 Mockito 项目中提出了同样的问题,将其替换为byte-buddybyte-buddy-agent将起作用。

然后我意识到 Ivy 不需要我明确列出子依赖项(我不知道它知道如何解决它们),因此我能够更新到这个更简单的ivy.xml ,它适用于 Ant 和IntelliJ 类似:

<ivy-module version="2.0">
  <info organisation="com.example" module="MockitoTest"/>
  <dependencies>
    <dependency org="junit" name="junit" rev="4.13.2"/>
    <dependency org="org.mockito" name="mockito-inline" rev="4.2.0"/>
  </dependencies>
</ivy-module>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM