[SPRING] 프록시가 작동하지 않는 CGLIB 서비스의 자산 조롱
SPRING프록시가 작동하지 않는 CGLIB 서비스의 자산 조롱
Junit 테스트에서 서비스의 속성을 조롱하려고 할 때 문제가 있습니다.
@ContextConfiguration("classpath:application-config.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class FooServiceTests {
@Autowired
private FooServiceImpl fooService;
@Test
public void testFoo() {
String str = fooService.foo();
assertEquals("Var", str);
}
@Before
public void mockFooDao() throws Exception {
FooDao mockFooDao = Mockito.mock(FooDao.class);
Mockito.when(mockFooDao.foo()).thenReturn("Var");
ReflectionTestUtils.setField(fooService, "fooDao", mockFooDao);
}
}
FooDao를 비웃는 것은 결과가 예상과 다르기 때문에 아무런 효과가 없습니다. 다음은 서비스와 dao의 코드입니다.
@Service("fooService")
public class FooServiceImpl implements FooService {
@Autowired
protected FooDao fooDao;
@Override
public String foo() {
return fooDao.foo();
}
}
@Repository
public class FooDaoImpl implements FooDao {
@Override
public String foo() {
return "foo";
}
}
우리가 볼 수 있듯이 실제 서비스는 "foo"를 반환하기위한 것이지만, 테스트는 "var"를 반환하도록 DAO를 조롱합니다. CGLIB 프록시 관련 일을 알고 있지만 fooDao 속성에 setter를 사용하지 않고 작동시키는 방법을 알 수는 없습니다. 어떤 도움을 주시면 감사하겠습니다.
감사와 사전에 감사드립니다.
해결법
-
==============================
1.프록시의 포장을 풀고 대상 객체의 필드를 설정해야합니다.
프록시의 포장을 풀고 대상 객체의 필드를 설정해야합니다.
ReflectionTestUtils.setField(unwrapFooService(), "fooDao", mockFooDao);
unwrapFooService ()는 다음과 같이 정의 할 수 있습니다.
private FooServiceImpl unwrapFooService() { if(AopUtils.isAopProxy(fooService) && fooService instanceof Advised) { Object target = ((Advised) fooService).getTargetSource().getTarget(); return (FooServiceImpl)target; } return null; }
문제는 상당히 복잡하지만 해결할 수 있습니다. 짐작 하시겠지만 이것은 CGLIB 프록시의 부작용입니다. 원칙적으로 Spring은 FooServiceImpl $ EnhancerByCGLIB와 비슷한 이름으로 FooServiceImpl의 하위 클래스를 만듭니다. 이 서브 클래스에는 원래 FooServiceImpl에 대한 참조뿐만 아니라 FooServiceImpl에있는 모든 필드가 포함됩니다 (이것은 이해할 수 있습니다 - 이것은 서브 클래스입니다).
실제로 FooServiceImpl $ EnhancerByCGLIB.fooDao와 FooServiceImpl.fooDao라는 두 가지 변수가 있습니다. 당신은 이전에 mock을 할당하고 있지만 서비스는 후자를 사용합니다 ... 나는이 함정에 대해 몇 시간 전에 썼습니다.
from https://stackoverflow.com/questions/9033874/mocking-a-property-of-a-cglib-proxied-service-not-working by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Mybatis 봄 여러 데이터베이스 Java 구성 (0) | 2019.02.01 |
---|---|
[SPRING] 스프링 구성 (0) | 2019.02.01 |
[SPRING] Hibernate에 의해로드 된 엔티티로 Spring을 통해 필드 주입 (0) | 2019.02.01 |
[SPRING] Spring JDBC 지원 및 대규모 데이터 세트 (0) | 2019.02.01 |
[SPRING] 스프링 부트에서 Postgres 연결이 닫혔다. (0) | 2019.02.01 |