코딩하는 오징어
Spring test 와 Junit4를 이용한 테스트 본문
반응형
Junit 4 & Spring Test을 이용한 TDD 환경 세팅
(다음은 Spring boot를 이용하지 않은 애플리케이션에서의 테스트 환경이다.)
- SpringTestSupport 클래스에 설정 후 이 클래스를 상속받아 테스트를 개발함.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { RootContextConfig.class }, loader = AnnotationConfigWebContextLoader.class) @WebAppConfiguration public class SpringTestSupport { @Autowired protected WebApplicationContext wac; protected MockMvc mockMvc; @Before public void setup() throws Exception { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @Test public void isWebAppContextLoadingProperly() { ServletContext servletContext = wac.getServletContext(); Assert.assertNotNull(servletContext); Assert.assertTrue(servletContext instanceof MockServletContext); Assert.assertNotNull(wac.getBean("rootContextConfig")); } }
@RunWith(SpringJUnit4ClassRunner.class)
- 이 애노테이션을 붙여줘야 스프링 테스트를 Junit으로 돌릴 수 있음.
@ContextConfiguration(classes = { RootContextConfig.class }, loader = AnnotationConfigWebContextLoader.class)
- RootContextConfig.class를 spring context의 빈 설정 파일로 사용한다는 의미.
@WebAppConfiguration
- 이 애너테이션을 붙이면 Controller및 web환경에 사용되는 빈들을 자동으로 생성하여 등록하게됨.
참고
- DB 프로퍼티 파일은 src/test/resource경로가 classpath로 잡히기 때문에 이 경로에 db.properties파일이 있어야 함.(dp.properties파일 이름은 src/main/resource 경로에 있는 파일명과 동일하게 지었음. 따로 테스트전용 리소스 파일을 관리하지않고 h2database만 설정하기 위함)
Controller 테스트 예제
public class UserControllerTest extends SpringTestSupport { @Test public void issueTokenApiTest() throws Exception { MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get("/v1/issue-token")) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().is(HttpStatus.OK.value())) .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andReturn(); Assert.assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, mvcResult.getResponse() .getContentType()); Assert.assertEquals(HttpStatus.OK.value(), mvcResult.getResponse() .getStatus()); } }
- spring integration test 참고 : https://www.baeldung.com/integration-testing-in-spring
h2database 설정 파일
# db connect setting datasource.driverClassName=org.h2.Driver datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1; datasource.username=codingsquid datasource.password=1234
Bean Mocking Test
- Controller를 테스트 할 경우 Service layer까지 내려가게됨. Controller만 테스트하고 싶다면 Service를 Mocking하면 됨.
- mocktio framework을 이용하여 적용해보자.
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
위와같은 import static을 통해 static method를 사용하게 하였다.
public class UserControllerTest extends SpringTestSupport { @Mock private UserService userService; @InjectMocks private UserController userController; @Test public void issueTokenApiIntegrateTest() throws Exception { this.mockMvc.perform(get("/v1/issue-token")) .andDo(print()) .andExpect(status().is(HttpStatus.OK.value())) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("$.result.token").exists()) .andExpect(jsonPath("$.result.created_at").exists()); } @Test public void issueTokenApiUnitTest() { MockitoAnnotations.initMocks(this); LocalDateTime testTime = LocalDateTime.now(); givenUserService(testTime); ApiResponseModel<AccessToken> result = userController.issueToken(); Assert.assertEquals(result.getCode(), HttpStatus.OK.value()); Assert.assertEquals(result.getMsg(), HttpStatus.OK.getReasonPhrase()); Assert.assertEquals(result.getResult().getToken(), "this is sample access-token"); Assert.assertEquals(result.getResult().getCreatedAt(), testTime); } private void givenUserService(LocalDateTime createdAt) { User mockUser = new User(); mockUser.setAccessToken(new AccessToken("this is sample access-token", createdAt)); when(userService.registerUser()).thenReturn(mockUser); } }
- Mocking전의 테스트 코드와 비교하여 달라진 점은 @Mock, @InjectMocks와 givenUserService 메서드가 추가돼고 MockitoAnnotations.initMocks(this); 줄이 포함됨. 하나씩 알아가 보자.
- @Mock -> Mocking할 빈을 설정 한다.
- @InjectMocks -> UserController빈을 Context에 등록할 때 연관관계를 가진 빈 대신 Mocking된 빈을 집어 넣는다.
- givenUserService에서 when 메서드에 userService의 registerUser()메서드가 호출되면 mockUser를 return하게 만든다.
- given, when, then 패턴을 알아두자.
- MockitoAnnotations.initMocks(this); -> 현재 테스트 클래스의 @Mock이 달린 객체를 초기화하는 작업이다. 첨언하자면 테스트 클래스는 @Test가 붙은 메서드마다 객체가 새로 만들어지게 되며 issueTokenApiUnitTest메서드가 호출될 때 새로 생성된 테스트 클래스의 객체를 파라미터로 넣어준다.
반응형
'Framework > Spring' 카테고리의 다른 글
Spring boot logback 설정 (0) | 2018.08.25 |
---|---|
Spring boot profile 적용하기 (1) | 2018.08.25 |
Spring boot starter test 와 Junit5를 이용한 테스트 (0) | 2018.08.24 |
Spring & JPA의 Hibernate 설정시 주의 사항 & CandidateComponentsIndexLoader 클래스 (0) | 2018.07.28 |
Spring web mvc & jpa - hibernate 빈 설정 (MAVEN) (0) | 2018.07.15 |
Comments