Spring Test Framework и проблема автопроводки на основе аннотаций

Я хотел бы использовать две разные реализации для DAO с тестовой средой Spring.

src.main.java

.businessobjects
   \-User.java
.dao
   \-IUserDAO.java
.daojpa
   \-UserDAO.java
.daohibernate
   \-UserDAO.java

Весенний тестовый пример в:

src.test.java.base:

package base;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/hibernate-beans.xml")
@Transactional
public abstract class SpringTestCase {}

И вот ошибка:

Вызвано: java.lang.IllegalStateException: указанное в аннотации имя компонента userDAO для класса компонента [jpadao.UserDAO] конфликтует с существующим несовместимым определением компонента с тем же именем и классом [jpaadao.UserDAO].

Я уже пытался переопределить автопроводку с помощью квалификаторов, например:

<bean class="jpaadao.UserDAO">
    <qualifier value="jpaa"/>
</bean>
<bean class="jpadao.UserDAO">
    <qualifier value="jpa"/>
</bean>

А затем в проводке testcase с

@Autowired
@Qualifier("jpa")
private IUserDAO userDAO;

но ошибка сохраняется.

Два вопроса:

  1. Как можно решить эту проблему с помощью конфигурации на основе аннотаций?
  2. Как запустить тесты БЕЗ автосвязывания и аннотаций?

person Ta Sas    schedule 08.07.2010    source источник


Ответы (4)


Вы используете bean-компоненты без имен, поэтому Spring попытается придумать имя, это имя может быть основано на аннотации @Component, которая у вас предположительно есть в вашем классе, но это также может быть верблюжья версия вашего неквалифицированного класса имя вашего bean-компонента (в обоих случаях они окажутся равными, и это вызывает возражения Spring).

Кроме того, кажется, что вы смешиваете сканирование компонентов и конфигурацию xml, что мне кажется немного странным.

Из этого есть много способов, но наиболее чисто вы бы использовали только один bean-компонент, реализующий контракт, который вы пытаетесь выполнить. Если вам нужны разные реализации, вы должны дать им разные и более описательные имена:

<bean id="jpaUserRepository" class="..JpaUserRepository"/>

Это даст вам более полезную регистрацию, даже если имена компонентов никогда не используются, потому что вы полагаетесь на автоматическое связывание.

person iwein    schedule 08.07.2010
comment
И я продолжал использовать @Autowired, а не @Resource? - person Ta Sas; 09.07.2010
comment
@Resource менее гибкий, чем @Autowired. Я бы использовал его только в том случае, если у вас не может быть зависимости Spring в классе, который вы подключаете к нему, и если вы используете Spring для подключения EJB. Ваш тестовый пример не имеет к этому никакого отношения, особенно с учетом того, что последние версии Spring 3 поддерживают устранение неоднозначности при сопоставлении имен полей. - person iwein; 10.07.2010

  1. Сделайте то, что предложил Ивейн: лучше назовите свои классы реализации (например, HibernateUserDao и JpaUserDao); или укажите уникальное имя компонента с помощью аннотации @Component или @Repository в классах реализации UserDAO.
  2. В настоящее время вы не можете запускать тесты без автоматического связывания. Подробнее см. в этом выпуске JIRA: https://jira.springsource.org/browse/SPR-6050

С уважением,

Сэм (автор Spring TestContext Framework)

p.s. Нет, проблема, с которой вы столкнулись, не связана с SPR-4524.

person Sam Brannen    schedule 11.07.2010

Вы можете попробовать внедрить зависимость по имени, используя аннотацию @Resource. Вам нужно будет дать имена (идентификаторы) компонентам или использовать значение по умолчанию, которое представляет собой неполное имя класса без заглавных букв.

person Bozho    schedule 08.07.2010
comment
Спасибо за ответ, но я пытался, но не получилось :-( - person Ta Sas; 08.07.2010
comment
Я получаю точно такую ​​же ошибку. Пожалуйста, подождите минутку, я запакую весь исходный код и выложу куда-нибудь для скачивания... - person Ta Sas; 08.07.2010
comment
Хо Божо. Я выложил для скачивания два пакета: drop.io/sof20100708_1 Один работает нормально (testspringanno.works.zip) а другой выдает ошибку (testspringanno.error.zip). Последний включает дополнительный пакет под названием de.sandbox.test.hibernateao. Полное сообщение об ошибке находится в файле testpringanno.error/target/surefire-reports/de.sandbox.test.dao.BodyStatDAOTest.txt. - person Ta Sas; 08.07.2010
comment
О, кстати, я попробовал что-то вроде @Resource(name = "jpaUserDAO") private IBodyStatDAO userDAO;, и это ничего не изменило. Даже после явного определения идентификатора компонента в appcontext.xml :-( - person Ta Sas; 08.07.2010

Я получил его и работает сейчас! Однако я не считаю, что это лучшая практика. Я просто исключил путь нежелательных DAO, написав в appContext.xml:

   <context:component-scan base-package="test">
        <context:exclude-filter type="regex" expression="test\.daohibernate.*"></context:exclude-filter>
    </context:component-scan>

Какие-либо предложения? Может ли эта проблема быть связана с http://jira.springframework.org/browse/SPR-4524< /а> ?

person Ta Sas    schedule 08.07.2010