Java static method와 Test wrapper

신석진( Seokjin Shin)·2024년 1월 31일
0

static method에 관하여 고찰을 하던 중, Mocking과 관련된 이야기를 들었다. 그래서 찾아보고 static method를 사용하는 클래스에서 어떻게 의존성을 관리해야할지를 찾던 중 인사이트를 발견하여 기록하고자한다.

일단 static method를 사용할 때는 의존성으로 class 전체를 의존성으로 주입받는 것은 의미가 없다. 왜냐하면 static은 해당 클래스 내부에 종속되기 때문에 의존성으로 주입한다고 해도 가져다 쓰기 어렵고 애당초 클래스로 받았으니 인스턴스화 해서 넘겼다는 것을 의미하므로 불필요하기도 하다. 또한 그렇게 했을 경우 해당 클래스 내부에서 일어나는 일들을 테스트에서 모킹할 수 없게 되어버린다.

그래서 고찰하던 도중 functional interface와 lambda를 발견하게 되었다. 이를 보고 생각한 것은 의존성을 주입해야할 대상은 static method를 포함하는 class가 아니라 static method 자체라고 생각을 했고 이를 람다를 통해 주입해주면 된다고 생각했다.

interface Downloader {
  public void download();
}

class FileDownloader {
  static void download(){
    System.out.println("download!");
  }
}

class Service {
  final Downloader downloader;
  
  Service(Downloader downloader){
    this.downloader = downloader;
  }
  
  void getFile(){
    downloader.download();
  }
}

var service = new Service(()->FileDownloader.download());

service.getFile(); //download!

위와 같은 코드로 작성하게되면 Test class에서는 생성시 다른 method를 주입해주면 된다.

public class ServiceTest {
    @Test
    void test() {
        var service = new Service(()->FileDownloader.download());
        assertEquals("download!", service.getFile());
        
        var mockService = new Service(() -> System.out.println("mocked!"));
        assertEquals("mocked!", mockService.getFile());
    }
}

사실 java에 대해서는 잘은 모르지만 static을 모킹한 순간 설계가 잘못되었다고 생각은 든다. 그래도 외부라이브러리 등에서 제공하는 static method를 쓰고 있다면 테스트를 위해서라도 항상 해당 method를 주입받아서 써야할 것 같다.

0개의 댓글