[SPRING] 프록시 때문에 봄베이 주입 실패
SPRING프록시 때문에 봄베이 주입 실패
스프링 버전 : 3.2.4.RELEASE 및 3.2.9.RELEASE
모키 토 버전 : 1.8.5
나는 통합 테스트를 위해 오래된 프로젝트에 H2 테스트를 도입하려고 노력해 왔으며 몇 가지 문제를 겪어왔다. 트랜잭션이 전파되는 방식 때문에 autowired 클래스를 조롱해야했습니다. 나는 전에 이것을했지만, 지금 나는 심각한 문제에 부딪치고있다. 테스트를 초기화 할 때 다음 오류 메시지가 발생합니다.
조금 더 깊숙이 들어가면 빈은 실제로 프록시입니다. AbstractBeanFactory (라운드 라인 239)를 체크하면 우리는 프록시를 볼 수있다 :
유일한 문제는 이것이 어디에서 오는 것인지 전혀 모른다는 것입니다. 구성 및 종속성을 살펴 보았으므로 아무 곳이나 찾을 수 없습니다.
불행히도이를위한 샘플 프로젝트를 제공 할 수는 없지만 테스트 구성을 살펴 보겠습니다. 테스트를 위해 확장 한 루트 클래스가 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/spring-test-context.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public abstract class AbstractIntegrationTest {
}
이것은 단순히 각 스프링 테스트에로드되고 각 테스트 후에 트랜잭션을 롤백합니다.
내 다른 모듈과이 모듈 사이에는 하나의 차이점이 있지만 봄 구성은 이상한 것도 아닙니다. 이것은 트랜잭션 관리자 및 세션 팩토리입니다.
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>
<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
...
</bean>
다른 모듈에서는 entityManagerFactory와 다른 트랜잭션 관리자를 사용하고 있습니다.
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>
실제 클래스에는 autowired 필드와 일반적인 @Service 주석이 있습니다.
@Service(value = "TheProcessor")
public final class XMLBatchFileProcessor extends BatchFileProcessor implements IXMLBatchProcessor {
마지막으로 실제 테스트는 다음과 같습니다.
public class XMLITCase extends AbstractIntegrationTest {
@Resource(name = "TheProcessor")
@InjectMocks
private XMLBatchFileProcessor xmlProcessor;
@Mock
private ProcessHelper processHelper;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() throws Exception {
Assert.assertNotNull(xmlProcessor);
}
}
XMLBatchFileProcessor를 인터페이스로 바꾸고 필드를 autowire하면 컴파일하는 데 문제가 없습니다. 그러나 Mockito는 autowired 빈을 조롱 된 객체로 대체하지 않습니다. 만약 그렇다면 @Resource 주석을 사용하고 서비스의 이름을 지정하지 않아도되므로 Proxy 문제를 피할 수 있습니다.
이것에 대한 어떤 도움도 감사 할 것입니다. 나는 세션 팩토리와 그 차이점에 초점을 맞추 겠지만, 내가 완전히 다른 것을 놓치고있는 것이 가능할 수도있다.
Sotirios의 코멘트를 살펴보면, 오늘 아침에 또 다른 모습을 보였습니다. xmlProcessor에 @Transactional 주석이 있으므로, 클래스가 프록시되어야한다는 의미입니다. 최종 선언문을 제거하고 CGLib가 그것을 향상 시키면, initMocks (this)가 호출 될 때 Mockito가 빈을 대체합니다. 그러나 메소드가 호출 될 때 CGLib는 모든 빈을 스프링 확장 버전으로 대체하여 Mockito 버전을 덮어 쓰는 것으로 보입니다.
@Transactional 어노테이션이있는 클래스의 통합 테스트에서 Mockito와 Spring을 모두 사용하는 올바른 방법은 무엇입니까?
해결법
-
==============================
1.좋아요, 일단 클래스가 @ Transactional 주석으로 인해 프록시되었다는 것을 알게되면 문제에 대한 해결책이 명확 해집니다. 필자가해야 할 일은 프록시의 포장을 풀고 조롱 된 객체를 직접 설정하는 것입니다.
좋아요, 일단 클래스가 @ Transactional 주석으로 인해 프록시되었다는 것을 알게되면 문제에 대한 해결책이 명확 해집니다. 필자가해야 할 일은 프록시의 포장을 풀고 조롱 된 객체를 직접 설정하는 것입니다.
그래서 내 AbstractIntegrationTest에서 :
/** * Checks if the given object is a proxy, and unwraps it if it is. * * @param bean The object to check * @return The unwrapped object that was proxied, else the object * @throws Exception */ public final Object unwrapProxy(Object bean) throws Exception { if (AopUtils.isAopProxy(bean) && bean instanceof Advised) { Advised advised = (Advised) bean; bean = advised.getTargetSource().getTarget(); } return bean; }
그럼 내 @ 전에 :
@Mock private ProcessHelper processHelper; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); IXMLBatchProcessor iXMLBatchProcessor = (IXMLBatchProcessor) unwrapProxy(xmlProcessor); ReflectionTestUtils.setField(iXMLBatchProcessor , "processHelper", processHelper); }
이렇게하면 모든 @Autowired 클래스가 손상되지 않고 올바른 객체가 주입됩니다.
from https://stackoverflow.com/questions/30648397/spring-bean-injection-failing-due-to-proxy by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring Boot Application에서 Angular 클라이언트가 여러 개인 RequestMapping 문제 (0) | 2019.05.04 |
---|---|
[SPRING] 봄 mvc에서 정적 콘텐츠를 제공하는 방법? (0) | 2019.05.04 |
[SPRING] Hibernate는 원치 않는 update 문을 실행한다. (0) | 2019.05.04 |
[SPRING] 봄 유레카 서버가 갱신 횟수가 임계 값보다 낮음을 보여줍니다. (0) | 2019.05.04 |
[SPRING] 스프링 MVC에서 브라우저 백 버튼 처리 방법 (0) | 2019.05.04 |