- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在下面显示的单元测试类中,其中一个测试失败,另一个测试成功。这两个测试都会创建一个带有拦截器模拟的 CGLIB 对象,并尝试验证拦截器是否与之交互。对于使用 CGLIB 动态子类化的类,测试有所不同。成功的测试子类化了一个普通的 Java 接口(interface);失败的子类是一个动态子类(使用 Mockito
创建)。为什么第一次测试失败?
谢谢。
public class ATest {
@Test
// This test fails.
public void cannotCallMethodOnMockWrapper() throws Throwable {
final Class<? extends Bar> c = Mockito.mock(Bar.class).getClass();
verifyInterceptorIsInvokedOnCallToObjectOfEnhanced(c);
}
@Test
// This test succeeds.
public void interceptorIsCalled() throws Throwable {
final Class<? extends Bar> c = Bar.class;
verifyInterceptorIsInvokedOnCallToObjectOfEnhanced(c);
}
private void verifyInterceptorIsInvokedOnCallToObjectOfEnhanced(
final Class<? extends Bar> c) throws Throwable {
final MethodInterceptor interceptor = Mockito.mock(
MethodInterceptor.class);
final Bar wrapper = (Bar) Enhancer.create(c, interceptor);
// Here is where the failing test chokes with exception:
// NoSuchMethodError
wrapper.foo();
verifyInterceptIsCalledOn(interceptor);
}
private void verifyInterceptIsCalledOn(
final MethodInterceptor interceptor) throws Throwable {
verify(interceptor).intercept(any(), any(Method.class),
any(Object[].class), any(MethodProxy.class));
}
public static interface Bar {
void foo();
}
}
更新:
失败的堆栈跟踪
java.lang.NoSuchMethodError: java.lang.Object.foo()V
at ATest$Bar$$EnhancerByMockitoWithCGLIB$$2e1d601f.foo(<generated>)
at ATest.verifyInterceptorIsInvokedOnCallToObjectOfEnhanced(ATest.java:37)
at ATest.cannotCallMethodOnMockWrapper(ATest.java:19)
此外,至于 Mockito 模拟是否是 CGLIB 增强类,下面的测试(失败)似乎表明它不是:
public class ATest {
@Test
public void mockitoMockIsCGLIBEnhanced() {
assertTrue(Enhancer.isEnhanced(Mockito.mock(Bar.class).getClass()));
}
public static interface Bar {
void foo();
}
}
最佳答案
如果没有堆栈跟踪,我会假设您有一个 net.sf.cglib.core.CodeGenerationException
,原因可能是 InvocableTargetException
或 ClassFormatError
,
发生这种情况是因为 CGLIB 无法增强它自己创建的已经增强的类。由于 Mockito 在 JVM 内部使用 CGLIB,因此您无法增强 Mockito 类。你需要增强原来的类。 此外,即使回调是一个实例,您也需要传递给生成的类,因此通过创建自己的增强器,您就没有上层类的 Mockito 回调。所以mockito模拟功能甚至无法工作。不管怎样,我偏离了主题。
所以基本上你不能用CGLIB增强增强类,如果这个问题在运行时发生,因为你传递了一个模拟,我相信你应该有这样的代码,检查它是否增强,如果是使用父类(super class)(原始类)和/或接口(interface):
public class CGLIBEnhancerEnhancer implements TypeEnhancer {
public void Object enhance(Object objectCandidateToEnhance, MethodInterceptor interceptor) {
Class classCandidateToEnhance = classCandidateToEnhance.getClass();
if(Enhancer.isEnhanced(classCandidateToEnhance)
|| Mockito.mockingDetails(objectCandidateToEnhance).isMock()) {
// safe with CGLIB (2.x) enhanced class
return (Bar) Enhancer.create(
classCandidateToEnhance.getSuperclass(),
classCandidateToEnhance.getInterfaces(),
interceptor
);
} else
return (Bar) Enhancer.create(classCandidateToEnhance, interceptor);
}
}
}
编辑:我运行了给定的示例,它确实给了我 CodeGenerationException
,您可以在本答案的末尾看到。尽管根据环境的不同,您可能会看到不同的堆栈跟踪,例如您发布的堆栈跟踪。
考虑到您的异常,我相信您可能在运行时遇到如何创建双增强类的问题。由于堆栈跟踪表明该实例甚至没有 foo 方法,因此就像该对象(似乎是真正的 mockito 模拟)是从错误的类型生成的。我会查看增强器的 API,以正确使用类型和接口(interface)来创建增强类,您可以使用 Enhancer
的新实例或使用静态方法。
此外,如果您自己证明拦截器,并且想要执行给定实例的行为(模拟或非模拟),则应该精心设计您的拦截器,使其保存对原始对象的引用。
编辑2:实际上,由于技术原因,Mockito正在重新打包/jarjar/内联CGLIB,这意味着net.sf.cglib.proxy.Enhancer
无法检测到mockito mock 。相反,人们应该使用 1.9.5 中新引入的 API Mockito.mockingDetails(instance).isMock()
来检测 mockito 模拟。或者使用重新打包/jarjared/内联的org.mockito.cglib.proxy.Enhancer
。最后,您需要在类路径中使用 Mockito 来检测 Mockito 模拟。
希望有帮助
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.create(Enhancer.java:286)
at org.mockito.cglib.proxy.Enhancer.create(Enhancer.java:664)
at ATest.verifyInterceptorIsInvokedOnCallToObjectOfEnhanced(ATest.java:32)
at ATest.cannotCallMethodOnMockWrapper(ATest.java:18)
... removed
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
... removed
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385)
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220)
... 31 more
Caused by: java.lang.ClassFormatError: Duplicate method name&signature in class file ATest$Bar$$EnhancerByMockitoWithCGLIB$$58a2468b$$EnhancerByCGLIB$$9232d1df
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
... 37 more
关于java - 为什么cglib调用MethodInterceptor回调失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13826705/
Spring不包含cglib依赖,cglib和spring cglib都有Enhancer类,一个是net.sf.cglib.proxy.Enhancer,另一个是org.springframewor
我正在尝试构建一个大型项目,但由于以下错误而失败: [INFO] -------------------------------------------------------------------
关闭。这个问题不符合 Stack Overflow guidelines 。它目前不接受答案。 想改善这个问题吗?更新问题,以便堆栈溢出为 on-topic。 7年前关闭。 Improve this
@Service public class TestService{ @DynamicReference private ITestProvider testProvider;
我有以下通用 cglib 方法拦截器实现: public class EntityInterceptor implements MethodInterceptor{ private Entit
假设我有一些 A 类,它具有 B 类的属性。 public class ClassA{ private ClassB classB; public ClassA(ClassB classB){ th
我正在使用 CGLib 来增强 A 类。 public class A { public void printName(){ System.out.println("guy");
我的 Controller 在其属性上使用了 @Value 注释,但是发生了一些奇怪的事情: 08:20:31.400 [main] ERROR Controller - postConstruct(
我想做的是序列化一个类实现一个命令模式,以便我稍后可以运行它。在最好的在所有世界中,我想序列化一个匿名类(我是意识到这个问题) 让事情变得有点复杂的是我在 Spring 的环境中并且我希望序列化的匿名
谁能给我一个 Java CGLib 的好例子 Mixin类用法?我一直在挖掘它们似乎都不够简单。 最佳答案 很简单: import static org.junit.Assert.*; import
在实际项目中,考虑到不同的数据使用者,我们经常要处理 VO、DTO、Entity、DO 等对象的转换,如果手动编写 setter/getter 方法一个个赋值,将非常繁琐且难维护。通常情况下,这类转换
代码如下: Patient patient = factory.createPatient(); Enhancer enhancer = new Enhancer(
我有两个类 @Component @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS,value="session") public clas
代码是用 Scala 编写的,但希望 Java 程序员也能理解。 我有以下类(class): class SampleClass { def test(in: String) = "Hello w
我无法为 HttpURLConnection 类创建动态代理,因为它没有公共(public)构造函数来创建增强器。根据要求,我想创建一个动态代理以在运行时获取当前连接的详细信息。 我尝试使用this教
我想使用 cglib 作为我的 spring 代理机制。问题是,我有一些 bean 的依赖项由构造函数注入(inject),我无法更改。 CGLIB 似乎不太喜欢这样,不会让我实例化那个 bean。有
当尝试将 CGLIB 与回调过滤器(在数万个对象上)一起使用时,我注意到速度很糟糕,但我无法找到有关优化 CGLIB 的任何信息。 对于搜索/列表界面,系统从优化的查询中加载多个属性,并使用这些属性填
我正在为生产 spring batch 项目构建端到端测试框架。我们想使用内存中的嵌入式数据库(在我们的例子中是 hsqldb)进行这些测试,因为它运行得更快并且没有环境限制。由于这些数据库引擎之间的
借助 cglib,我可以使用以下代码创建延迟实例化的 BigInteger: Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Bi
我有一个正在开发的 Java 库,它使用 cglib 创建库用户提供的抽象类的子类,并提供自动生成的用户留在其中的抽象方法的实现。 我的问题是,如果有问题的方法具有包本地(即默认)可访问性,我生成的方
我是一名优秀的程序员,十分优秀!