簡體   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