2013-05-22 4 views
1

이상한 피험자는 질문 자체를 계속 진행합니다. 스프링 응용 프로그램 컨텍스트에서 스프링 테스트 클래스에 접근 할 수있는 방법이 있습니까?스프링 컨텍스트에서 Spring 테스트 클래스 객체에 액세스

@Component 
public class SimpleDaoHandler implements ApplicationContextAware, InitializingBean { 
    private ApplicationContext applicationContext; 
    private static Logger logger = Logger.getLogger(SimpleDaoHandler.class); 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     //I have the application context now, via method "setApplicationContext" 
     // and need to get test class object to get the 
     // annotated field "TestAnnotation" because I also need to set this 
     // field with my business logic, using reflection. 
     // Problem is; test class object is not included in the 
     // "applicationContext" as a bean and I don't know how to access my 
     //test class which is already starting the spring context initialization. 
     //I need to get that test class object. 
    } 

    @Override 
    public void setApplicationContext(final ApplicationContext applicationContext) 
      throws BeansException { 
     this.applicationContext = applicationContext; 
    } 

단서 :

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/applicationContext-core.xml") 
public class DbFuntionTests { 

    @TestAnnotation 
    private UserSessionDao userSessionDao; 

    @Test 
    public void testOracleTimestamp() throws Exception { 
     userSessionDao.findAll(); 
    } 
} 

스프링 컨텍스트의 초기화 후 핸들러 클래스 : 질문 세부 사항은 주석 블록 :

테스트 클래스로 "SimpleDaoHandler"클래스에 숨겨져있다?

답변

1

@TestAnnotation과 호환되는 post processor을 만드는 것이 더 좋을 수도 있습니다. @Autowire이라는 주석이 달린 필드/메소드가있는 빈을 스캔하고 처리하는 스프링 AutowiredAnnotationBeanPostProcessor을 살펴볼 수 있습니다. 나는 이것이 여러분이 성취하려고 시도하는 것으로 생각하며, 빈 포스트 프로세서는 그러한 문제들에 대해 가능한 가장 깨끗한 해결책이다 (Spring 자체에서 사용됨).

응용 프로그램 컨텍스트 내의 각 빈에 대해 MyAnnotation에 대한 MyAnnotationPostProcessor 스캔을 검사하고 해당 필드를 기록하십시오. (물론 로깅 대신 당신은 어떤 행동을 취할 수 있습니다;)). 주석에 RetentionPolicy.RUNTIME이 선언되어 있어야합니다. 그렇지 않으면 런타임에 표시되지 않습니다.

public final class MyAnnotationPostProcessor implements BeanPostProcessor { 

    private static final Log LOG = LogFactory.getLog(MyAnnotationPostProcessor.class); 

    public Object postProcessBeforeInitialization(Object bean, String beanName) 
      throws BeansException { 
     final Set<Field> annotatedFields = getAnnotatedFields(bean.getClass()); 
     for (Field annotatedField : annotatedFields) { 
      LOG.info("Post process before initialization " + beanName + "," + annotatedField); 
     } 
     return bean; 
    } 

    public Object postProcessAfterInitialization(Object bean, String beanName) 
      throws BeansException { 
     final Set<Field> annotatedFields = getAnnotatedFields(bean.getClass()); 
     for (Field annotatedField : annotatedFields) { 
      LOG.info("Post process after initialization " + beanName + "," + annotatedField); 
     } 
     return bean; 
    } 

    private Set<Field> getAnnotatedFields(final Class<?> clazz) { 
     final Set<Field> annotatedFields = new HashSet<Field>(); 
     for (Field field : clazz.getDeclaredFields()) { 
      if(hasMyAnnotation(field)) { 
       annotatedFields.add(field); 
      } 
     } 
     return annotatedFields; 
    } 

    private boolean hasMyAnnotation(final AccessibleObject ao) { 
     return AnnotationUtils.getAnnotation(ao, MyAnnotation.class) != null; 
    } 
} 

테스트 클래스와 주석 : Piotrek 드에

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(loader=AnnotationConfigContextLoader.class) 
public class MySpringTest { 

    @MyAnnotation 
    private UserSessionDAO dao; 

    @Configuration 
    static class TestContext { 
     @Bean 
     public static MyAnnotationPostProcessor myAnnotationPostProcessor() { 
      return new MyAnnotationPostProcessor(); 
     } 
    } 

    @Test 
    public void test() { 

    } 
} 

@Target({ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 

} 
+0

당신은 맞습니다. @Autowired와 AutowiredAnnotationBeanPostProcessor가이 작업을 수행 할 수있는 방법이 있지만 코드가 너무 복잡해서 코드가 너무 복잡해서 코드를 이해하기 어렵습니다. :)). 어떤 방법 으로든, 당신의 답은 다른 종류의 후 처리기를 시도하도록 이끌어줍니다. 어떤 결과라도 얻으면, 당신에게 알려줄 것입니다. 답장을 보내 주셔서 감사합니다. – MartK

+0

그래, 복잡해 보이지만, 자동 완성 로직을 구현했기 때문에 - @Autowired annotation lookup 때문이 아니다.) - 사용자 정의 어노테이션으로 작업하는 간단한 포스트 프로세서의 예를 보여 주었다. –

+0

당신의 대답은 더 자세합니다, 그래서 저는 제 대답을 선택했습니다 :) 시청자들은 아래의 답을 찾을 수 있습니다. – MartK

0

덕분에, 나는 마침내 해답을 발견했다. 어노테이션 처리기 클래스도 BeanPostProcessor 클래스를 구현해야합니다. 테스트 컨텍스트 리스너가이 방법에 도달 할 때마다

@Override 
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
    try { 
     injectGDao(bean); 
    } catch (Exception e) { 
     throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause()); 
    } 
    return bean; 
} 

@Override 
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
    try { 
     injectGDao(bean); 
    } catch (Exception e) { 
     throw new BeanInstantiationException(bean.getClass(), e.getMessage(), e.getCause()); 
    } 
    return bean; 
} 

, 당신은 이제 테스트 클래스 객체에 도달 할 수 있습니다 :이 방법은, 당신은뿐만 아니라 테스트 응용 프로그램 컨텍스트에서 사용하는 두 가지 방법을 얻을. 앞서 언급 한 Piotrek De의 답변에서 더 자세한 답변을 찾을 수 있습니다.

관련 문제