<aside> 1️⃣ Mock이 뭘까?

</aside>

<aside> 2️⃣ 왜 테스트에서 Mock 객체를 사용하는걸까?

</aside>

<aside> 3️⃣ 주요 어노테이션

</aside>

  1. @SpringBootTest:

    @SpringBootTest
    public class MyServiceIntegrationTest {
        @Autowired
        private MyService myService;
    
        @Test
        public void testMyService() {
            // myService를 이용한 테스트 코드 작성
        }
    }
    
  2. @AutoConfigureMockMvc:

  3. @MockBean

  1. 1,2,3 통합적용한 controller 테스트 코드

    @Service
    public class MyService {
        // 실제로는 데이터베이스나 다른 외부 자원과 상호작용하는 코드가 있을 수 있습니다.
        // 이 예시에서는 단순히 123L을 반환하도록 합니다.
    
        public long countItems() {
            return 123L;
        }
    }
    
    @RestController
    public class MyController {
        @Autowired
        private MyService myService;
    
        @GetMapping("/items/count")
        public String getItemsCount() {
            long count = myService.countItems();
            return String.valueOf(count);
        }
    }
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class MyControllerTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @MockBean
        private MyService myService;
    
        @Test
        public void whenTestController_thenCorrect() throws Exception {
            Mockito.when(myService.countItems()).thenReturn(123L);
    
            mockMvc.perform(get("/items/count"))
                .andExpect(status().isOk())
                .andExpect(content().string("123"));
        }
    }
    
  2. @Mock

    @Service
    public class MyService {
        @Autowired
        private MyRepository myRepository;
    
        public long countItems() {
            return myRepository.count();
        }
    }
    
    @Repository
    public interface MyRepository extends JpaRepository<MyEntity, Long> {
    }
    
    @SpringBootTest
    public class MyServiceTest {
    
        @Mock
        private MyRepository myRepository;
    
        @InjectMocks
        @Autowired
        private MyService myService;
    
        @Test
        public void whenUseMockAnnotation_thenCorrect() {
    				//여기서 mock의 동작을 설정한다.
            Mockito.when(myRepository.count()).thenReturn(123L);
    
            long count = myService.countItems();
    
            assertEquals(123L, count);
        }
    }
    
  3. @InjectMocks

    @Component
    public class MyList {
        private List<String> list = new ArrayList<>();
    
        public void add(String item) {
            list.add(item);
        }
    
        public int size() {
            return list.size();
        }
    }
    
    @Service
    public class MyService {
        @Autowired
        private MyList myList;
    
        public void addItem(String item) {
            myList.add(item);
        }
    
        public int getItemCount() {
            return myList.size();
        }
    }
    
    @SpringBootTest
    public class MyServiceTest {
    
        @Mock
        private MyList mockMyList;
    
        @InjectMocks
        @Autowired
        private MyService myService;
    
        @Test
        public void whenUseInjectMocksAnnotation_thenCorrect() {
            myService.addItem("one");
            Mockito.verify(mockMyList).add("one");
    
            Mockito.when(mockMyList.size()).thenReturn(100);
            assertEquals(100, myService.getItemCount());
        }
    }
    
  4. @Spy

    @Spy
    private List<String> spyList = new ArrayList<>();
    
    @Test
    public void whenUseSpyAnnotation_thenSpyIsInjectedCorrectly() {
        spyList.add("one");
        spyList.add("two");
    
        Mockito.verify(spyList).add("one");
        Mockito.verify(spyList).add("two");
    
        assertEquals(2, spyList.size());
    
        Mockito.doReturn(100).when(spyList).size();
        assertEquals(100, spyList.size());
    }
    

    위의 코드에서, @Spy 어노테이션을 사용하여 **ArrayList<String>**의 인스턴스 **spyList**를 Spy 객체로 생성했습니다. **spyList.add("one")**과 **spyList.add("two")**를 호출하면 실제로 아이템이 추가되고 리스트의 크기는 2가 됩니다. 그런 다음 **Mockito.doReturn(100).when(spyList).size();**을 통해 size() 메소드가 호출되면 100을 반환하도록 설정했습니다. 따라서 **assertEquals(100, spyList.size());**는 통과합니다.

  5. @Captor

    @Mock
    private List<String> mockList;
    
    @Captor
    private ArgumentCaptor<String> argCaptor;
    
    @Test
    public void whenUseCaptorAnnotation_thenTheSam() {
        mockList.add("one");
        Mockito.verify(mockList).add(argCaptor.capture());
    
        assertEquals("one", argCaptor.getValue());
    }