12

问题

Cobertura 仪器在特定情况下会破坏自动接线的弹簧。有谁知道如何解决这个问题?

设想

  • 我正在使用 cobertura-maven-plugin 版本 2.5.1 运行 MVN 3.0.4。
  • mvn 测试运行没有问题
  • mvn compile、package 等也可以正常运行。
  • mvn cobertura:cobertura 在添加 2 个新功能之前也没有任何问题,这些新功能引入了许多新类,包括两个新的 com.mycompany.executor 执行器类。(示例:除了现有的 MyExecutor 之外,还添加了 MyHappyExecutor 和 MySadExecutor)
  • 从 cobertura 检测过程中排除 MyExecutor 似乎可以修复自动装配
  • 检查 spring 自动装配输出确认正确的 bean 正在自动装配。

故障点

尝试在 myService 中自动装配 myExecutor 的检测版本时,自动装配失败。这在添加 MyHappyExecutor 和 MySadExecutor 之前运行良好。MyHappyExecutor 和 MySadExecutor 是自动装配的,并专门在 MyExecutor 中使用。

我在下面附上了异常输出。请不要编辑类和包名称。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mycompany.executor.MyExecutor com.mycompany.service.impl.MyServiceImpl.myExecutor; 
nested exception is java.lang.IllegalArgumentException: Can not set com.mycompany.executor.MyExecutor field com.mycompany.service.impl.MyServiceImpl.myExecutor to $Proxy20

结论

Cobertura 仪表过程中的某些东西弄乱了 Springs 的自动装配。

更新 1

强制 CGLIB 类代理会将错误类型更改为“java.lang.NoClassDefFoundError”错误。这会影响标准测试目标以及 Cobertura 目标。

<aop:config proxy-target-class="true"/>

更新 2

这是相关 3 个类的 springs 启动过程的输出。

2012-11-01 16:21:51 INFO  [main] Overriding bean definition for bean 'myExecutor': replacing [Generic bean: class [com.mycompany.executor.MyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.MyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)
2012-11-01 16:21:51 INFO  [main] Overriding bean definition for bean 'happyExecutor': replacing [Generic bean: class [com.mycompany.executor.HappyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.HappyExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)
2012-11-01 16:21:51 INFO  [main] Overriding bean definition for bean 'sadExecutor': replacing [Generic bean: class [com.mycompany.executor.SadExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] with [Generic bean: class [com.mycompany.executor.SadExecutor]; scope=; abstract=false; lazyInit=false; autowireMode=1; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [configuration.xml]] - (DefaultListableBeanFactory.java:623)
4

3 回答 3

1

另一种选择是让执行器实现一个接口(比如说执行器)并在 MyService 中使用接口注入。Spring 将知道如何构建代理以实现接口。大多数时候,我更喜欢这种方法来代替 proxyTargetClass。

于 2015-07-23T21:02:40.460 回答
0

对于您的测试,您需要设置proxyTargetClass=true

@EnableTransactionManagement(mode=AdviceMode.ASPECTJ, proxyTargetClass=true)

如果这适用于您的测试,但是当您运行您的应用程序时它失败了,那么您需要为测试和您的应用程序单独配置。测试配置集proxyTargetClass=true和应用配置集proxyTargetClass=false

对于您的NoClassDefFoundError错误,我们需要查看堆栈跟踪。你可能没有包含 spring-aop 库

于 2012-11-07T02:55:15.297 回答
0

我们有一个关于 Aspect 和包私有类的类似问题。我们的修复非常简单,因为我们可以将我们的包私有类公开。

在那之后,还有更多关于 cobertura 的问题,我们搬到了 JaCoCo,并且对结果非常满意。默认情况下,使用 cobertura 的 maven 构建是这样配置的:

  • 运行测试
  • 通过 cobertura 检测代码
  • 再次运行测试并测量覆盖率

由于 JaCoCo 使用代理而不是字节码工具来测量代码覆盖率,因此测试只运行一次,从而使构建方式更快。

如果您需要有关设置 JaCoCo 的更多信息,请参阅此链接。

于 2017-02-16T16:25:59.413 回答