[SPRING] Test 코드 만들기

림민지·2025년 4월 25일

Today I Learn

목록 보기
50/62

📌 TestCode 만들기

우리가 하고 싶은 것!!

"가게 주인이 새로운 가게를 만들면, 진짜 잘 만들어지는지 확인하고 싶어!"
➡️ StoreServiceImpl에서 createStore 메서드가 잘 작동하니?

테스트 코드에게 조건과 Mock(거짓된, 가짜의) 객체들을 넣어주고
그 객체를 넣었을 때 메서드가 잘 돌아가니?

StoreServiceImpl 클래스

//StoreServiceImpl 클래스
   @Override
    public StoreResponseDto.Complete createStore(Long ownerId, StoreRequestDto.Create dto) {

        User user = userRepository.findById(ownerId).orElseThrow(
                () -> new ApiException(ErrorStatus.USER_NOT_FOUND));

        if (user.getUserRole() != UserRole.OWNER) {
            throw new ApiException(ErrorStatus.STORE_NO_PERMISSION);}

        int storeCount = storeRepository.countByUserIdAndDeletedFalse(ownerId);
        if (storeCount >= 3) {
            throw new ApiException(ErrorStatus.STORE_MAX_LIMIT_EXCEEDED);}

        if (storeRepository.existsByName(dto.getName())) {
            throw new ApiException(ErrorStatus.STORE_ALREADY_EXISTS);}

        Store newStore = new Store(user, dto);
        storeRepository.save(newStore);

        return new StoreResponseDto.Complete("가게가 생성되었습니다.");
    }

서비스 클래스를 보면,
주인의 ID
RequestDto를 받아서 실행된다

이 실행에 필요한 가짜 객체들을 만들어서 이걸 쓰렴~하고 알려주고 결과를 받아보자!!


0. 사전 설정

  1. @Mock
    :가짜 객체를 만드는 역할
@Mock
private StoreRepository storeRepository;
@Mock
private UserRepository userRepository;

테스트할 때 진짜 데이터베이스나 외부 시스템을 쓰면 느리고 복잡하니까 진짜가 아닌 가짜 객체를 만들기
→ 추후에 storeRepository.findById() 같은 메서드를 실제로 실행하지 않고, 내가 원하는 값만 딱! 줄 수 있도록 설정할 수 있따

given(storeRepository.existsByName("가게이름")).willReturn(false);
  1. @InjectMocks
    : 가짜 객체들을 이 클래스에 주입해주
@InjectMocks
private StoreServiceImpl storeService;

위에 만든 가짜 객체들(@Mock)을 여기 안에 자동으로 넣어준다

1. 가게를 만들 주인 유저 생성

Long ownerId = 1L; // 주인의 번호

User user = new User(
    "222@gmail.com",    // 이메일
    "1133Aaa.",         // 비밀번호
    "이름",             // 이름
    UserRole.OWNER,     // 주인 역할
    "별명",
    "010-4274-0774",
    "주소",
    Gender.MALE,
    LocalDate.of(2002, 12, 18),
    24
);

→ "1번 사용자"가 가게를 만들 거라고 미리 준비(owner_id = 1)

2. 가게 객체 생성

StoreRequestDto.Create request = StoreRequestDto.Create.builder()
    .name("가게 이름")             
    .address("주소")             
    .openTime(LocalTime.of(11,0)) 
    .closeTime(LocalTime.of(21,0))
    .minOrderPrice(3000)          
    .deliveryFee(10000)          
    .notice("공지")                
    .status(Status.OPEN)          
    .phone("010-3333-1111")    
    .build();

→ 1번 사용자의 가게를 만들어주자

3. createStore 메서드 내의 로직들의 결과를 넣어주기

테스트 코드를 실행할 때 레포지토리에 실제로 저장된 값들을 가져오는게 아니니까,
레포지토리를 사용한 결과들은 테스트 코드가 알수가 없자나요..?
그러니까 우리가 이 부분은 이걸로 사용하도록해!(given) 이라고 알려주는것

userRepository.findById(ownerId);
storeRepository.countByUserIdAndDeletedFalse(ownerId);
storeRepository.existsByName(dto.getName());

createStore에서는 요 3개의 로직 결과를 넣어주어야 createStore를 실행할 수가 있겠죵

given(userRepository.findById(ownerId)).willReturn(Optional.of(user));
given(storeRepository.countByUserIdAndDeletedFalse(ownerId)).willReturn(1);
given(storeRepository.existsByName(request.getName())).willReturn(false);

given().willReturn() 메서드를 통해 결과를 만들어놔주자
.willReturn() 여기 괄호 안에 들어가는 결과가 테스트 코드가 받을 결과!!

4. 진짜 가게 만들기 실행!

StoreResponseDto.Complete responseDto = storeService.createStore(
               ownerId,request);

5. 결과 확인

assertEquals("가게가 생성되었습니다.", responseDto.getMessage());

6. 커버리지 확인

왼쪽에 초록색 줄들이 생긴 것을 볼 수 있다.
초록색은 커버리지가 된 부분, 빨강 노랑은 아직 안된 부분을 뜻한다!
이 표시들이 모두 초록색이 될 수 있도록, 커버리지가 100이 될 수 있도록 계속해서 진행하면 된다!!

그리고 이렇게 커버리지가 몇퍼센트정도 진행됐는지 오른쪽의 커버리지탭에서 확인이 가능하다


전체 코드

package com.example.toanyone.domain.store;
import com.example.toanyone.domain.store.dto.StoreRequestDto;
import com.example.toanyone.domain.store.dto.StoreResponseDto;
import com.example.toanyone.domain.store.enums.Status;
import com.example.toanyone.domain.store.repository.StoreRepository;
import com.example.toanyone.domain.store.service.StoreServiceImpl;
import com.example.toanyone.domain.user.entity.User;
import com.example.toanyone.domain.user.enums.Gender;
import com.example.toanyone.domain.user.enums.UserRole;
import com.example.toanyone.domain.user.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.BDDMockito.given;


@ExtendWith(MockitoExtension.class)
public class StoreServiceTest {
    @Mock
    private StoreRepository storeRepository;
    @Mock
    private UserRepository userRepository;
    @InjectMocks
    private StoreServiceImpl storeService;

    @Test
    void 가게_생성_성공(){

        Long ownerId = 1L;
        User user = new User("222@gmail.com",
                "1133Aaa.",
                "이름",
                UserRole.OWNER,
                "별명",
                "010-4274-0774",
                "주소",
                Gender.MALE,
                LocalDate.of(2002  , 12, 18),
                24);

        StoreRequestDto.Create request = StoreRequestDto.Create.builder()
                .name("가게 이름")
                .address("주소")
                .openTime(LocalTime.of(11,0,0))
                .closeTime(LocalTime.of(21,0,0))
                .minOrderPrice(3000)
                .deliveryFee(10000)
                .notice("공지")
                .status(Status.OPEN)
                .phone("010-3333-1111")
                .build();

       // ✅ GIVEN — 준비(상황 설정)
       given(userRepository.findById(ownerId)).willReturn(Optional.of(user));
       given(storeRepository.countByUserIdAndDeletedFalse(ownerId)).willReturn(1);
       given(storeRepository.existsByName(request.getName())).willReturn(false);

 		// ✅ WHEN — 실행 (내가 테스트할 메서드 실행)
        StoreResponseDto.Complete responseDto = storeService.createStore(
                ownerId,request);


		 // ✅ THEN — 검증 (결과 확인)
        assertEquals("가게가 생성되었습니다.", responseDto.getMessage());
    }
}
profile
@lim_128

0개의 댓글