Подтвердить что ты не робот

Spring @Автоматизированный сбой в случае инструментального класса Cobertura

Вопрос

Инструмент Cobertura разбивает автопогрузчики пружин в конкретном случае. Кто-нибудь знает, как это решить?

Сценарий

  • Я запускаю MVN 3.0.4 с версией 2.5.1 cobertura-maven-plugin.
  • Тест mvn без проблем
  • mvn compile, package etc также работает без проблем.
  • mvn cobertura: cobertura также работал без каких-либо проблем вплоть до добавления двух новых функций, которые ввели ряд новых классов, в том числе два новых класса com.mycompany.executor. (Пример: MyHappyExecutor и MySadExecutor были добавлены в дополнение к существующему MyExecutor)
  • Исключение MyExecutor из процесса сборки cobertura, похоже, устраняет autowiring
  • Проверка вывода autwiring spring подтверждает, что правильные beans становятся автообновленными.

Точка отказа

При попытке автоуверсии инструментальной версии myExecutor в myService происходит автоматическое завершение Autowiring. Это отлично работало перед добавлением 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 классов, о которых идет речь.

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)
4b9b3361

Ответ 1

Еще один вариант заключается в том, чтобы исполнители реализовали интерфейс (скажем, Executor) и ввели использование интерфейса в MyService. Spring будет знать, как создать прокси-сервер, чтобы он реализовал интерфейс. В большинстве случаев я предпочитаю этот подход к proxyTargetClass.

Ответ 2

Для ваших тестов вам нужно установить proxyTargetClass=true

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

Если это работает для ваших тестов, но когда вы запускаете приложение, оно терпит неудачу, тогда вам нужны отдельные конфигурации для тестов и для вашего приложения. Тестовые конфигурации конфигурации proxyTargetClass=true, а App config устанавливает proxyTargetClass=false

Для вашей ошибки NoClassDefFoundError нам нужно увидеть stacktrace. Вероятно, вы не включили spring -aop library

Ответ 3

У нас была аналогичная проблема, касающаяся классов Aspect и private-private. Наше исправление было довольно простым, так как мы могли просто сделать наш пакетно-закрытый класс общедоступным.

После этого и более проблем с cobertura мы перешли в JaCoCo и очень довольны результатом. По умолчанию сборка maven с cobertura настраивается следующим образом:

  • Запустите тесты
  • Измерить код через cobertura
  • Повторите тесты и измерьте охват

Поскольку JaCoCo использует агент вместо инструментария байт-кода для измерения охвата кода, тесты выполняются только один раз, что делает способ сборки быстрее.

Смотрите эту ссылку, если вам нужна дополнительная информация о настройке JaCoCo.