[Spring] 테스트 코드 작성 (JUNIT)

SeoHa·2025년 6월 19일

SPRING

목록 보기
3/7

스프링 테스트 코드 작성 - Junit5 + Mockito


1. 필드 선언

@Mock : Mapper를 가짜(mock) 객체로 만든다.
→ 실제 DB 접근 없이 테스트 가능하게 함.

예시
private ReservationMapper reservationMapper; --> 필수로 필요

private final Long memberId = 3L; --> set해줄 값이 필요할 때만
private final String role = "DROPPER";
private final String state = "CONFIRMED";

@InjectMocks : 해당Mapper를 주입해 해당ServiceImpl 인스턴스를 만들어준다

예시
private ReservationServiceImpl reservationService;


2. 테스트 시작 전 초기화

@BeforeEach : 테스트 시작 전 초기화

  • 매 테스트 메서드 실행 전에 Mockito가 @Mock, @InjectMocks를 초기화해서 사용할 수 있게 함.

    
    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this); // @Mock과 @InjectMocks 초기화
    }
    

3. 테스트 메서드 작성

1. given : 테스트 조건 생성

DTO객체를 생성해줍니다.

set을 사용해서 dto에서 필요한 값을 생성해줍니다.

Mockito를 사용해 특정 메서드 호출 시 원하는 값을 리턴하도록 설정합니다.
ex) Mockito.when(Mapper.findUserById(lockerId)).thenReturn(mockResponse); : Mapper.findUserById(lockerId) 호출 시, 실제 DB를 조회하지 않고 mockResponse를 반환하라는 뜻

  • DTO명 Response/Request = new DTO명 -> 객체 생성
  • 객체명.set~~ 해서 필요한 값 생성해주기
    - 리스트 : List<타입> 변수명 = List.of("", "");
    • find 테스트 시에는 DTO중에 필요한 것만 (받아와야하는 값들만)
    • insert 테스트 시에는 DTO에 있는 필드 다 SET 해주기 (build()로 해도 가능)
  • 해당Mapper.메서드() 호출 시 -> mockResponse 반환하도록 모킹 / 필요한 값 반환하도록 모킹

  	**<예시>**
    
		해당DTO명 mockResponse = new 해당DTO명(); //find 테스트 (객체 생성)
		//해당DTO명 mockRequest = new 해당DTO명(); //insert 테스트 (객체 생성)

		mockResponse.setLockerId(lockerId);
		mockResponse.setLockerName("테스트 락커");
		List<String> mockImages = List.of("img1.jpg", "img2");
            
		//find 테스트
    	Mockito.when(Mapper.findUserById(lockerId)).thenReturn(mockResponse);
  		Mockito.when(Mapper.findImageById(lockerId)).thenReturn(mockImages);
		//insert 테스트
		//Mockito.doNothing().when(Mapper).insert(mockRequest);
		//Mockito.when(Mapper.findLastInsertedId()).thenReturn(1L);
 

2. when : 실제 테스트 대상 메서드 호출

서비스 메서드를 호출하고 그 결과를 해당 DTO로 받아옵니다.

  • find 테스트 시에는 해당DTO명 result = Service.메서드명(받을 변수명 ex)lockerId );
  • insert 테스트 시에는 Long lockerId = Service.메서드명(받을 객체 ex)mockRequest );
 	**<예시>**
		//find 테스트
 		해당DTO명 result = Service.findUserById(lockerId);
        //insert 테스트
        Long lockerId = lockerService.registerLocker(mockRequest);

3. then : 결과 검증

결과값이 기대값인지 확인합니다.

<단위 테스트에서 결과를 검증할 때 사용하는 메서드>
assertNotNull(~) : null이 아닌지 검사
assertEquals(확인할 값, get해준 값) : 기대값인지 확인
assertTrue () : 해당 값이 ture

  • assertNotNull(서비스 매서드 결과값) : 서비스 매서드 결과값이 null이 아닌지 검사

  • assertEquals(확인할 값, 매서드 결과값.get해준 값) : 기대값인지 확인

    		**<예시>**
    
    			assertNotNull(result);
    			assertEquals(lockerId, result.getLockerId());
    			assertEquals("테스트 락커", result.getLockerName());
    			assertEquals(2, result.getImages().size());
    			assertEquals("img1.jpg", result.getImages().get(0));

4. 두번째 테스트 메서드 - 예외케이스

1. given

  • 존재하지 않는 'lockerId = 값'에 대해 'Mapper.findUserById(값)'가 null을 반환하도록 모킹

2. when

  • Service.메서드명(값) 실행 시, 해당 lockerId가 없으니 Exception 예외가 발생하는지 테스트
	**<예시>**

		Exception exception = assertThrows(LockerException.class, () -> {
			Service.findUserById(lockerId);
		});

3. then

  • 발생한 예외의 상태 코드가 NOT_FOUND_LOCKERDETAILS인지 검증
	**<예시>**
         assertSame(BaseResponseStatus.NOT_FOUND_LOCKERDETAILS, exception.getBaseResponseStatus());

테스트 클래스 그룹화

@Nested

  • JUnit 5에서 제공하는 기능으로, 테스트 클래스를 논리적으로 그룹화할 수 있게 도와주는 애노테이션이다.
  • 하나의 테스트 클래스 안에서 상황, 조건, 기능별로 테스트 코드를 묶고 싶을 때 사용한다.

예시
정상 케이스 vs 예외 케이스
파라미터 유효성 검사


< 의존성 추가 >

<!-- JUnit5 -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.5.0</version>
      <scope>test</scope>
    </dependency>
<!--JUnit 5 - Mockito-->
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <version>5.11.0</version>
      <scope>test</scope>
    </dependency>

4개의 댓글

comment-user-thumbnail
2025년 6월 19일

좋은 정보 감사합니당!

답글 달기
comment-user-thumbnail
2025년 6월 20일

헉 이해가 쏘옥쏘옥 너무 좋은 글 감사합니다!!

답글 달기
comment-user-thumbnail
2025년 6월 20일

좋은 정보 감사합니댭 ><

1개의 답글