본문 바로가기
Old Posts/Java

[Java] @VisibleForTesting 애너테이션

by A6K 2020. 9. 30.

자바 코드에서 @VisibleForTesting 애너테이션은 해당 메소드 혹은 멤버 변수의 가시성(Visibility)이 테스트를 위해 완화된 것임을 명시적으로 나타내는 의미다.

자바의 경우 프로그래밍을 할 때, 비즈니스 로직을 담고 있는 클래스와 테스트 클래스를 분리한다. 그리고 이 두 클래스를 같은 패키지에 두는 것이 일반적이다. 이렇게 되면, 비즈니스 로직을 담고 있는 클래스의 private 멤버나 메서드를 테스트 클래스에서 접근할 수 없다.

비즈니스 로직을 담고 있는 클래스는 캡슐화(Encapsulation)를 위해서 불필요하게 메서드나 멤버 변수를 외부로 노출시키지 않는 것이 좋다. 그렇다고 private 메서드의 테스트를 안할 수는 없다. 이 때 사용하는 것이 @VisibleForTesting 애너테이션이다.

private 메서드를 package-private 으로 완화하고 그 위에다가 @VisibleForTesting 을 붙여주자. 단, Java 단에서 뭔가를 강제하거나 하는 것은 없다. 문서화를 위한 것일 뿐.. 실제로 다른 클래스에서 호출하면 호출된다.

package user;

import com.google.common.annotations.VisibleForTesting;

public class UserClass {

    @VisibleForTesting
    String getHello() {

        return "Hello";
    }
}

비즈니스 로직을 담고 있는 UserClass가 있다고 하자.

package user;

import org.junit.Test;
import static org.junit.Assert.*;

public class UserClassTest {
    @Test
    public void getHello() {

        UserClass userClass = new UserClass();

        assertEquals("Hello", userClass.getHello());
    }
}

이 클래스를 테스트하는 클래스는 이런 모습일 것이다.

package user;

public class OtherClass {

    private final UserClass userClass;

    public OtherClass() {

        this.userClass = new UserClass();
    }

    public void sayHello() {

        String hello = this.userClass.getHello();
        System.out.println(hello);
    }

    public static void main(String[] args) {

        OtherClass otherClass = new OtherClass();
        otherClass.sayHello();
    }
}

@VisibleForTesting 애너테이션을 붙였지만 정상적으로 호출되긴한다. 하지만 같은 패키지 내에만 열어두었으므로 호출하는 입장에서는 테스트 케이스가 아니면 @VisibleForTesting 애너테이션이 붙은 메서드를 호출하지 말아야 한다.

이 애너테이션을 사용하려면 guava 라이브러리를 참조해야한다. 메이븐 프로젝트의 경우 다음과 같은 의존성 추가가 필요할 수 있다.

<dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>13.0</version>
</dependency>

 

댓글