看起来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)
但是,使用java
或scala
按预期方式运行:
> 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)吗?
答案 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”,
```