从SBT运行Mockito时出现java.lang.IllegalAccessError

时间:2014-01-29 15:07:07

标签: sbt mockito

看起来SBT用Mockito加载混乱。

项目/ Build.scala

import sbt._
import Keys._
import sbtassembly.Plugin._
import AssemblyKeys._

object Build extends Build {
  lazy val root = project.in(file("."))
    .settings(
      name := "so-mockito",
      compileOrder := CompileOrder.JavaThenScala,
      libraryDependencies += "org.mockito" % "mockito-core" % "1.9.5"
    )
    .settings(buildSettings: _*)
    .settings(assemblySettings: _*)
    .settings(mainClass in assembly := Some("com.example.JavaMain"))
}

项目/ plugins.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.10.2")

的src /主/ JAVA / COM /示例/ Consumer.java

package com.example;

class Consumer {
    interface Input {
        String get();
    }

    private final Input input;

    static Consumer create(Input input) {
        return new Consumer(input);
    }

    private Consumer(Input input) {
        this.input = input;
    }
}

的src /主/ JAVA / COM /示例/ JavaMain.java

package com.example;

import static org.mockito.Mockito.*;
import static com.example.Consumer.*;

public class JavaMain {
    public static void main(String[] args) {
        final Input input = mock(Input.class);
        System.out.println(String.format("[JavaMain] Created mock: '%s'", input));
    }
}

sbt run产生以下异常:

[info] Running com.example.JavaMain 
[error] (run-main-0) org.mockito.exceptions.base.MockitoException: 
[error] Mockito cannot mock this class: interface com.example.Consumer$Input
[error] Mockito can only mock visible & non-final classes.
[error] If you're not sure why you're getting this error, please report to the mailing list.
org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: interface com.example.Consumer$Input
Mockito can only mock visible & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
    at com.example.JavaMain.main(JavaMain.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImposterizer.java:110)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
    at org.mockito.Mockito.mock(Mockito.java:1243)
    at org.mockito.Mockito.mock(Mockito.java:1120)
    at com.example.JavaMain.main(JavaMain.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImposterizer.java:110)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
    at org.mockito.Mockito.mock(Mockito.java:1243)
    at org.mockito.Mockito.mock(Mockito.java:1120)
    at com.example.JavaMain.main(JavaMain.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
Caused by: java.lang.IllegalAccessError: class com.example.Consumer$Input$$EnhancerByMockitoWithCGLIB$$5997e3ec cannot access its superinterface com.example.Consumer$Input
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImposterizer.java:110)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
    at org.mockito.Mockito.mock(Mockito.java:1243)
    at org.mockito.Mockito.mock(Mockito.java:1120)
    at com.example.JavaMain.main(JavaMain.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

但是,使用javascala按预期方式运行:

> sbt assembly && java -jar target/scala-2.10/so-mockito-assembly-0.1-SNAPSHOT.jar
[JavaMain] Created mock: 'Mock for Input, hashCode: 1317029026'

> sbt assembly && scala -cp target/scala-2.10/so-mockito-assembly-0.1-SNAPSHOT.jar 'com.example.JavaMain'
[JavaMain] Created mock: 'Mock for Input, hashCode: 1035091326'

任何人都可以确认(SBT 0.13.1)吗?

2 个答案:

答案 0 :(得分:0)

当内部com.example.Consumer.Input接口的访问修饰符变为public时,它可以正常工作,如下所示(注意接口的public关键字):

package com.example;

class Consumer {
    public interface Input {
        String get();
    }

    private final Input input;

    static Consumer create(Input input) {
        return new Consumer(input);
    }

    private Consumer(Input input) {
        this.input = input;
    }
}

之前使用sbt run的示例about来了解版本,插件等。

$ sbt about run
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/mockito/project
[info] Set current project to so-mockito (in build file:/Users/jacek/sandbox/so/mockito/)
[info] This is sbt 0.13.1
[info] The current project is {file:/Users/jacek/sandbox/so/mockito/}root 0.1-SNAPSHOT
[info] The current project is built against Scala 2.10.3
[info] Available Plugins: com.typesafe.sbt.SbtGit, com.typesafe.sbt.SbtProguard, growl.GrowlingTests, np.Plugin, com.timushev.sbt.updates.UpdatesPlugin, sbtassembly.Plugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.3
[info] Running com.example.JavaMain
[JavaMain] Created mock: 'Mock for Input, hashCode: 256995217'
[success] Total time: 0 s, completed Jan 29, 2014 10:00:13 PM

BTW,在使用build.sbt的这个特定构建配置中,可能是一个更好的选择,因为它会变得更清晰。

<强> build.sbt

import AssemblyKeys._

name := "so-mockito"

compileOrder := CompileOrder.JavaThenScala

libraryDependencies += "org.mockito" % "mockito-core" % "1.9.5"

sbtassembly.Plugin.buildSettings

sbtassembly.Plugin.assemblySettings

mainClass in assembly := Some("com.example.JavaMain")

答案 1 :(得分:0)

当我从scala代码gets()模拟flyway时,我遇到了类似的错误,测试通过Intellij很好地运行但是通过sbt测试它引发了: mock[org.flywaydb.core.Flyway] 对于其他谷歌我的解决方案只是升级mockito核心:

``` - “org.mockito”%“mockito-core”%“2.7.22”, +“org.mockito”%“mockito-core”%“2.15.0”,

```