본문 바로가기
Spring/인프런 토비의 Spring Boot

섹션 5-2 [DI와 테스트, 디자인 패턴] DI와 단위 테스트

by include_hoany 2024. 6. 12.

DI와 단위 테스트

5-1 섹션 에서는 Spring 서버에 직접적으로 네트워크 통신을 통해 테스트를 진행 하다 보니 테스트 수행 속도가 오래 걸리지만 아래 코드처럼 HelloService를 테스트를 진행 할 때는 네트워크를 통신을 하지 않고 Java객체를 직접적으로 호출하여 테스트 하므로 수행 속도가 월등히 빠릅니다.

 

package com.tobyspring.tobyspringboot;  
  
import org.assertj.core.api.Assertions;  
import org.junit.jupiter.api.Test;  
  
public class HelloServiceTest {  
  
    @Test  
    void simpleHelloService() {  
        HelloService helloService = new SimpleHelloService();  
        String result = helloService.sayHello("Test");  
        Assertions.assertThat(result).isEqualTo("Hello Test");  
    }  
  
}

 

직접 Spring을 의존하지 않고 자바 객체 생성 만으로 객체를 테스트 한다면 장점이 있는데  
바로 고립된 테스트가 가능하다는 점 입니다.  

HelloController가 의존하고 있는 HelloService로 부터 고립시켜 테스트가 가능합니다.  
HelloController 객체가 생성 될때 익명으로 HelloService구현체를 직접 주입하여  
HelloService에서 발생할 수 있는 오류를 제외하고 온전히 HelloController만 테스트할  
수 있게 됩니다.  
  
HelloController가 의존하는 HelloService를 직접 구현하여 주입하는 객체를  
Test Stub이라고도 부릅니다.

 

package com.tobyspring.tobyspringboot;  
  
import org.junit.jupiter.api.Test;  
  
public class HelloControllerTest {  

    @Test  
    void helloController() {  
        HelloController helloController = new HelloController(name -> name);  
        String result = helloController.hello("Test");  
    }  
  
}

 

테스트를 진행할때 성공케이스가 아닌 오류값이 파라미터로 전달될때 정의한 에러가 잘 발생하는지도 테스트할 수 있습니다.  helloController.hello 메소드에 null을 입력할 경우 NullPointerException.class 오류가 발생하는지 테스트할 수 있습니다. NullPointerException이 발생하지 않을경우 해당 테스트는 실패하게 됩니다.

 

@Test  
void failHelloController() {  
    HelloController helloController = new HelloController(name -> name);  
    Assertions.assertThatThrownBy(() -> helloController.hello(null)).isInstanceOf(NullPointerException.class);  
}

 

null뿐만아니라 name 파라미터값이 빈 공백 문자일경우에도 오류가 발생하도록 추가적으로 테스트할 수 있습니다.

 

@Test  
void failHelloController() {  
    HelloController helloController = new HelloController(name -> name);  
    Assertions.assertThatThrownBy(() -> helloController.hello(null)).isInstanceOf(IllegalArgumentException.class);  
    Assertions.assertThatThrownBy(() -> helloController.hello("")).isInstanceOf(IllegalArgumentException.class);  
}

 

위처럼 단위 테스트를 Spring Container를 의존하지 않고 테스트를 진행하면 빠르고 다양하게 테스트를 진행할 수 있습니다.

단위의 정의 느슨하기도 해서 단위 라는 정의는 각 도메인 팀의 그라운드룰마다 다를 수 있습니다.

네트워크 통신을 통한 실패 오류에대한 테스트또한 진행할 수 있습니다.

 

@Test  
void failHelloApi() {  
  
    TestRestTemplate rest = new TestRestTemplate();  
  
    ResponseEntity<String> response  
            = rest.getForEntity("http://localhost:8080/hello?name", String.class);  
  
    /*  
        응답 검증  
        State code: 500
    */
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);  
  
}