2016-03-07 1 views
1

Я не могу понять, почему происходит следующий простой сценарий: у меня есть приложение Spring с фильтром, который загружает компонент Spring из контекста приложения:Spring Test + Mockito.mock - Spring не работает, потому что он пытается загрузить издеваемую компоненту @Autowired зависимостей

public class MyFilter implements Filter{ 

    private IPermissionService permissionService; 

    public void init(FilterConfig filterConfig) throws ServletException { 
     WebApplicationContext ac = null; 
     try{ 
      ac = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext()); 
      permissionService = ac.getBean(PermissionServiceImpl.class); 

PermissionServiceImpl имеет @Autowired атрибут DATASOURCE так в моем TestNG тест, я высмеивать его в весеннем ApplicationContext:

@Configuration 
public class MyFilterSpringTestConfig{ 

    @Bean 
    public IPermissionService permissionService(){ 
     return Mockito.mock(PermissionServiceImpl.class); 
    } 

MyTest:

@Test 
@WebAppConfiguration 
@ContextConfiguration(classes=MyFilterSpringTestConfig.class) 
public class MyFilterSpringTest extends BaseSpringFilterTest{ 

    ... 

Проблема в том, что при инициализации Spring я получаю исключение, жалующееся на то, что зависимость DataSource от PermissionServiceImpl не выполняется. Поскольку я завернул его в макет, почему он все еще не работает? Как я могу это исправить?

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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), @org.springframework.beans.factory.annotation.Qualifier(value=myDataSource)} 
+0

Не издевайтесь над классом, издевайтесь над интерфейсом. Если вы создаете макет класса, он по-прежнему является экземпляром этого класса со всеми переменными и аннотациями с ним, которые, в свою очередь, все еще сканируются. Поэтому вы должны издеваться над интерфейсом (а также программировать на интерфейсы, а не на конкретные классы, как сейчас). –

+0

Вы правы насмехаетесь над интерфейсом. Однако в этом случае будут два фильтра: Filter1 для PermissionServiceImpl и Filter2 для PermissionServiceImpl2. Разработчик должен определить фильтр, который они предпочитают в web.xml, и импортировать соответствующий контекст весны для PermissionServiceImpl или PermissionServiceImpl2, в зависимости от фильтра. Использование 'permissionService = ac.getBean (PermissionServiceImpl.class);' в фильтре помогает гарантировать, что они не импортировали неправильный xml – codependent

+0

. Тогда в чем смысл использования интерфейса ... Используйте профили или другой способ подключения или создать 2 интерфейса , зачем вам 2 реализации одного и того же интерфейса и 2 фильтра? Кажется, что-то не так в первую очередь с этой установкой. Похоже, вы пытаетесь что-то построить, что вам не следует делать в первую очередь ... –

ответ

2

При издевательском классе с использованием Mockito (или любой другой издевательской структуры) этот класс по-прежнему является экземпляром исходного класса. При этом он также содержит все аннотации и информацию о классе.

Итак, когда вы создаете макет класса, он все еще обнаруживает все аннотации и пытается полностью заполнить это. То есть @Autowire другие экземпляры.

Либо не используйте автоматическую проводку, либо не издевайтесь над классом, кроме интерфейса (который не содержит эту информацию).