Вставить макет в боб не удалось - PullRequest
0 голосов
/ 09 сентября 2011

Для моих модульных тестов я хочу использовать mocks для некоторых автопроводных зависимостей тестируемого компонента. Макет создается и корректно вводится в класс модульных тестов, но его внедрение в тестируемый компонент завершилось неудачно с

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [Service] found for
dependency: expected at least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Это мой использованный testContext.xml

<bean id="Service" class="org.easymock.EasyMock" factory-method="createMock">
    <constructor-arg  value="Service" ></constructor-arg>
</bean>

<bean id="Controller" class="Controller">
    <property name="Service" ref="Service"></property>
</bean>

Это часть тестируемого компонента (Controller.java), в которой произошел сбой проводки

@Autowired
private Service service;

Но если я автоматически подключу тот же макет к своему классу модульного теста (ControllerTest.java), ошибки не будет,

@Autowired
private Service service;

Введенный объект имеет тип

($Proxy18) EasyMock for interface Service

Есть ли какие-либо предположения, почему инъекция в тестируемый боб невозможна, но инъекция в тест работает?

С уважением Dominik

Ответы [ 2 ]

2 голосов
/ 09 сентября 2011

Я думаю, что проблема может быть связана с порядком вещей. В ControllerTest я предполагаю, что вы расширяете AbstractJUnit4SpringContextTests или что-то подобное, что сначала соединяет все ваши бины (еще до того, как у вас появится шанс создать свой макет). Трудно сказать, не видя весь ваш класс (или, по крайней мере, объявление класса, setUp, tearDown и особый метод теста).

Обычная вещь для модульных тестов (в отличие от интеграционных тестов) состоит в том, чтобы вообще не использовать пружину, чтобы связать что-либо - просто используйте установщики свойств, чтобы внедрить ваших фиктивных соавторов вручную. Интеграционные тесты обычно не используют макеты - они используют реальные объекты.

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

1 голос
/ 09 сентября 2011

Возможно, это связано со случайным эффектом: порядком реализации бина Spring.

Глядя на фрагмент конфигурации контекста вашего приложения, у Spring нет способа узнать, что он должен сначала создать фиктивный объект типа Service, потому что он не знает, что создание экземпляра компонента с идентификатором Service приведет к типу Service. Это может предотвратить автоматическое подключение, если компонент Controller создается первым.

Чтобы подтвердить это, попробуйте

<bean id="Controller" class="Controller" depends-on="Service">

(РЕДАКТИРОВАТЬ: вы используете autowiring И явное свойство в конфигурации xml для Service. Что произойдет, если вы удалите @Autowired из Controller.Service?)

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

...