본문 바로가기

Server Development/Testing

Unit Test with MVC

 

 

스프링에서 어떻게 단위테스트를 하는지 간략히 보려고한다.

보통 스프링은 controller - service - DAO 구조로 이루어지고 클래스들을 어떻게 단위테스트하는지 알아보려고 한다.

 

또한, 방식은 가정-실행-결과 순으로 이루어진다.

 

가정 : 어떤 조건이 주어지고 그 결과는 이렇다고 정해져있을 때,

실행 : 해당 가정을 통해 이 클래스를 실행하면,

결과 : 이런 결과를 가져온다. 

 

 

아래 예시는 회원가입에 대한 간단한 단위테스트이다.

 

 

1. Controller

 

@WebMvcTest : 해당 클래스를 테스트 한다, Controller에만 사용할 수 있으며, 실제 실행이 아닌 가짜 실행이다.

@Autowired : 실제 주입을 의미하는데, 여기서 MockMvc는 HTTP 통신을 위한 클래스이다. 이는 실제를 가정하므로 실제로 주입한다.

@MockBean : 가짜 객체 주입이다, Controller는 동작 안에 MeberService에 대한 동작이 작성되어 있다. MockBean을 통해 실제로 실행하지는 않지만 가정을 통해 어떤 결과를 가져올지를 가정할 수 있다.

@Test : 단위 테스트마다 붙이는 태그

@DisplayName : 단위테스트 결과에 붙여줄 텍스트 명

 

아래 프로그램은 /member 라는 uri에 포스트 방식으로 어떤 리소스를 보낼 때, 이미 결과가 정해져 있는 Service를 통해 어떤 Controller 결과를 가져오는지 확인하는 테스트 코드이다.

@WebMvcTest(MemberController.class)

public class MemberControllerUnitTest {

  @Autowired
  private MockMvc mockMvc;

  @MockBean
  MemberServiceImpl memberService;


  @Test
  @DisplayName("회원가입 테스트")
  void getProductTest() throws Exception {

	  
	    // given
	    MemberDTO sample = MemberDTO.sample();	
	    given(memberService.registerMember(sample)).willReturn(sample);
	    Gson gson = new Gson();
	    String content = gson.toJson(sample);
	
	    
	    // when
	    ResultActions actions = mockMvc.perform(post("/member")
				.content(content)
				.contentType(MediaType.APPLICATION_JSON)
				.accept(MediaType.APPLICATION_JSON));
				
	    
	    // then
	    ResultActions realResult = actions.andExpect(status().isOk())
				.andExpect(jsonPath("$.userId").exists())
				.andExpect(jsonPath("$.userPwd").exists())
				.andExpect(jsonPath("$.userName").exists())
				.andExpect(jsonPath("$.userNumber").exists())
				.andExpect(jsonPath("$.userAddress").exists())
				.andExpect(jsonPath("$.userEmail").exists())
				.andDo(print());
	    verify(memberService).registerMember(sample);
  }

}

 

 

 

2. Service

 

@ExtendWith(MockitoExtension.class) : 이를 통해 가짜 객체 생성을 위한 선언

@InjectMocks : 실제 인스턴스를 생성하고 @Mock을 주입받는다.

@Mock : 가짜 객체 생성

@ExtendWith(MockitoExtension.class)
public class MemberServiceUnitTest {
	
	
	
	  @InjectMocks
	  private MemberServiceImpl memberService;
	
	  @Mock
	  private MemberDAO memberDAO;
	  
	  
	  @Test
	  @DisplayName("회원가입 테스트")
	  public void saveProductTest() {
		  
		    
		  //given
		  MemberDTO sample = MemberDTO.sample();
		  Mockito.when(memberDAO.existsById(sample.getUserId())).thenReturn(false);
		  Mockito.when(memberDAO.create(any(MemberEntity.class))).thenReturn(any(MemberEntity.class));


		    
		  // when
		  MemberDTO testDTO = memberService.registerMember(sample);
	
		    
		  // then
		  Assertions.assertEquals(testDTO.getUserId(), sample.getUserId());
		  Assertions.assertEquals(testDTO.getUserPwd(), sample.getUserPwd());
		  Assertions.assertEquals(testDTO.getUserName(), sample.getUserName());
		  Assertions.assertEquals(testDTO.getUserEmail(), sample.getUserEmail());
		  Assertions.assertEquals(testDTO.getUserAddress(), sample.getUserAddress());
		  Assertions.assertEquals(testDTO.getUserNumber(), sample.getUserNumber());
		  verify(memberDAO).create(any(MemberEntity.class));
	  }
	  
	  
}

 

 

 

 

3. DAO

 

@SpringBootTest

- 모든 빈을 가져와 사용가능한 환경을 만든다. 보통은 통합테스트 환경에서 쓰인다

- 쿼리문을 잘 전달하는지를 확인하기 위해서는 실제로 데이터를 넣어보고 결과를 가져올 필요가 있음

- SpringBootTest는 쿼리 처리 후 자동으로 rollback 해주기 때문에 다시 데이터를 지울 필요가 없음

 

위의 Controller, Service 같은 경우는 테스팅시 실제로 동작하지는 않는다. 하지만 DAO 테스팅 같은 경우, 실제로 동작이 이루어지기 때문에 아래의 애너테이션을 사용한듯 싶다.

@SpringBootTest
public class MemberDAOUnitTest {
	
	@Autowired
    	MemberRepository memberRepository;
	
	@DisplayName("회원 가입")
        @Test
        void addUser() {
            // given
            MemberDTO sampleMember = MemberDTO.sample();
            MemberEntity sampleEntity = new MemberEntity(sampleMember);

            // when
            MemberEntity savedMember = memberRepository.save(sampleEntity);

            // then
            assertThat(savedMember.getUserId()).isEqualTo(sampleEntity.getUserId());
            assertThat(savedMember.getUserPwd()).isEqualTo(sampleEntity.getUserPwd());
            assertThat(savedMember.getUserName()).isEqualTo(sampleEntity.getUserName());
            assertThat(savedMember.getUserEmail()).isEqualTo(sampleEntity.getUserEmail());
            assertThat(savedMember.getUserNumber()).isEqualTo(sampleEntity.getUserNumber());
            assertThat(savedMember.getUserAddress()).isEqualTo(sampleEntity.getUserAddress());
        }

}

'Server Development > Testing' 카테고리의 다른 글

Apache Jmeter  (0) 2023.05.15
Test Coverage with Jacoco  (0) 2023.04.02
Swagger  (0) 2023.04.01
TDD  (0) 2023.03.27
Testing HTTP Request with Insomnia  (0) 2023.03.27