private method test

greenTea·2023년 12월 2일
0

Java 리플렉션과 Spring의 ReflectionTestUtils를 이용한 프라이빗 메소드 및 필드 테스팅 🤖

자바 개발자라면 누구나 한 번쯤은 프라이빗 메소드나 필드를 테스트해야 할 상황에 직면할 수 있습니다. 이러한 상황이 온다면 Java의 리플렉션 API와 Spring Framework의 ReflectionTestUtils 클래스를 활용한다면 private이 붙어 있는 메소드나 필드를 테스트 할 수 있습니다.

코드 🛠

먼저, 테스트 대상인 MessageService 클래스와 그 필드를 살펴보겠습니다:

class MessageService {
    private Integer messageCount = 100;

    public String createMessage(String recipient) {
        return prepareMessage(recipient);
    }

    private String prepareMessage(String recipient) {
        return "Hello, " + recipient;
    }
}

이 클래스는 prepareMessage라는 프라이빗 메소드를 가지고 있으며, messageCount라는 프라이빗 필드를 포함하고 있습니다.

프라이빗 메소드 테스트하기 🕵️‍

프라이빗 메소드에 접근하기 위해 Java의 리플렉션 API를 사용해보겠습니다:

@SneakyThrows
@DisplayName("ReflectionTest")
@Test
void reflectionTest() {
    MessageService messageService = new MessageService();
    Method privateMethod = messageService.getClass()
                                         .getDeclaredMethod("prepareMessage", String.class);
    privateMethod.setAccessible(true);
    String result = (String) privateMethod.invoke(messageService, "john");
    System.out.println(result); // "Hello, john"
}

getDeclaredMethodsetAccessible(true)를 사용하여 프라이빗 메소드에 접근할 수 있습니다. 이 방법은 Java의 기본 기능을 사용하지만, 코드가 다소 복잡해 보일 수 있습니다.

Spring의 ReflectionTestUtils 사용하기 🌸

Spring에서 제공하는 ReflectionTestUtils를 사용하면 좀 더 간결하게 프라이빗 메소드와 필드를 테스트할 수 있습니다:

@DisplayName("ReflectionTestUtilsTest")
@Test
void reflectionTestUtilsTest() {
    MessageService messageService = new MessageService();

    String message = ReflectionTestUtils.invokeMethod(
        messageService,
        "prepareMessage",
        "World"
    );
    assertThat(message).isEqualTo("Hello, World");

    Integer count = (Integer) ReflectionTestUtils.getField(messageService, "messageCount");
    assertThat(count).isEqualTo(100);

    ReflectionTestUtils.setField(messageService, "messageCount", 250);

    Integer updatedCount = (Integer) ReflectionTestUtils.getField(messageService, "messageCount");
    assertThat(updatedCount).isEqualTo(250);
}

이 코드는 ReflectionTestUtils를 사용하여 프라이빗 메소드를 호출하고, 프라이빗 필드의 값을 가져오고 수정합니다.

ReflectionTestUtils.getField()를 통해 해당 필드를 가져올 수 있으며 (private,public 상관 없이 가져 올 수 있습니다.)

ReflectionTestUtils.setField()를 통해 필드의 값을 변경할 수도 있습니다.

ReflectionTestUtils는 Spring 테스트 환경에서 매우 유용하며, 코드를 더 간결하고 읽기 쉽게 만들어 줍니다.

그 외

다른 방법중의 하나로 private을 가지는 메소드나 필드를 public으로 교체하거나 아예 분리시켜서 하나의 클래스로(접근 할 수 있는 접근자 사용) 만드는 방법도 있습니다.

결론 ✨

🤔Java 리플렉션과 Spring의 ReflectionTestUtils는 강력한 도구로서, 보통은 접근할 수 없는 프라이빗 메소드와 필드에 접근할 수 있게 해줍니다. 하지만 이러한 기능을 사용할 때는 주의가 필요합니다. 프라이빗 메소드와 필드는 외부에서 접근하지 못하도록 의도적으로 숨겨져 있기 때문에, 리플렉션을 사용해 접근하는 것은 클래스의 캡슐화 원칙을 위반할 수 있습니다.
또한 리플렉션의 기능은 비용이 비싸기에 남발하게 된다면 성능에 있어 좋지 않습니다.

만약 private 접근자를 가지는 메소드나 필드를 테스트를 해야한다고 느껴진다면 다시 한번 해당 해당 구조가 맞는지 고민을 해봐야 합니다. 위와 같은 경우 잘 못된 구조를 가지고 있을 수 있기에 분리하는 것이 좋습니다.

따라서, 리플렉션은 테스트 목적으로만 제한적으로 사용해야 하며, 애플리케이션의 일반적인 로직에서는 피하는 것이 좋습니다.

참고자료 및 출처 : Spring Webflux 완전 정복 :
코루틴부터 리액티브 MSA 프로젝트까지

profile
greenTea입니다.

0개의 댓글