diff --git a/rest-api-with-spring/pom.xml b/rest-api-with-spring/pom.xml index 27aa684..db9615e 100644 --- a/rest-api-with-spring/pom.xml +++ b/rest-api-with-spring/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.0.RELEASE + 2.2.5.RELEASE diff --git a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/common/ErrorsResource.java b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/common/ErrorsResource.java index 5db8084..72f976f 100644 --- a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/common/ErrorsResource.java +++ b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/common/ErrorsResource.java @@ -1,14 +1,14 @@ package me.whiteship.demoinfleanrestapi.common; import me.whiteship.demoinfleanrestapi.index.IndexController; +import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; import org.springframework.validation.Errors; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; -public class ErrorsResource extends Resource { +public class ErrorsResource extends EntityModel { public ErrorsResource(Errors content, Link... links) { super(content, links); add(linkTo(methodOn(IndexController.class).index()).withRel("index")); diff --git a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventController.java b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventController.java index de225b1..a182e7e 100644 --- a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventController.java +++ b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventController.java @@ -9,7 +9,6 @@ import org.springframework.data.web.PagedResourcesAssembler; import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.mvc.ControllerLinkBuilder; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -20,10 +19,10 @@ import java.net.URI; import java.util.Optional; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; @Controller -@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_UTF8_VALUE) +@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE) public class EventController { private final EventRepository eventRepository; @@ -56,7 +55,7 @@ public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, event.setManager(currentUser); Event newEvent = this.eventRepository.save(event); - ControllerLinkBuilder selfLinkBuilder = linkTo(EventController.class).slash(newEvent.getId()); + var selfLinkBuilder = linkTo(EventController.class).slash(newEvent.getId()); URI createdUri = selfLinkBuilder.toUri(); EventResource eventResource = new EventResource(event); eventResource.add(linkTo(EventController.class).withRel("query-events")); @@ -70,7 +69,7 @@ public ResponseEntity queryEvents(Pageable pageable, PagedResourcesAssembler assembler, @CurrentUser Account account) { Page page = this.eventRepository.findAll(pageable); - var pagedResources = assembler.toResource(page, e -> new EventResource(e)); + var pagedResources = assembler.toModel(page, e -> new EventResource(e)); pagedResources.add(new Link("/docs/index.html#resources-events-list").withRel("profile")); if (account != null) { pagedResources.add(linkTo(EventController.class).withRel("create-event")); diff --git a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventResource.java b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventResource.java index fdd9c98..2d11fee 100644 --- a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventResource.java +++ b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/events/EventResource.java @@ -1,11 +1,11 @@ package me.whiteship.demoinfleanrestapi.events; +import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.hateoas.Resource; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; -public class EventResource extends Resource { +public class EventResource extends EntityModel { public EventResource(Event event, Link... links) { super(event, links); diff --git a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/index/IndexController.java b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/index/IndexController.java index 7641403..2fd18db 100644 --- a/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/index/IndexController.java +++ b/rest-api-with-spring/src/main/java/me/whiteship/demoinfleanrestapi/index/IndexController.java @@ -1,18 +1,18 @@ package me.whiteship.demoinfleanrestapi.index; import me.whiteship.demoinfleanrestapi.events.EventController; -import org.springframework.hateoas.ResourceSupport; +import org.springframework.hateoas.RepresentationModel; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; @RestController public class IndexController { @GetMapping("/api") - public ResourceSupport index() { - var index = new ResourceSupport(); + public RepresentationModel index() { + var index = new RepresentationModel(); index.add(linkTo(EventController.class).withRel("events")); return index; } diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/DemoApplicationTests.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/DemoApplicationTests.java deleted file mode 100644 index 0336373..0000000 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/DemoApplicationTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package me.whiteship.demoinfleanrestapi; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -@ActiveProfiles("test") -public class DemoApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/accounts/AccountServiceTest.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/accounts/AccountServiceTest.java index 917ac56..3afe94f 100644 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/accounts/AccountServiceTest.java +++ b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/accounts/AccountServiceTest.java @@ -1,32 +1,19 @@ package me.whiteship.demoinfleanrestapi.accounts; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; +import me.whiteship.demoinfleanrestapi.common.BaseTest; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertThrows; -@RunWith(SpringRunner.class) -@SpringBootTest -@ActiveProfiles("test") -public class AccountServiceTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); +public class AccountServiceTest extends BaseTest { @Autowired AccountService accountService; @@ -56,13 +43,7 @@ public void findByUsername() { @Test public void findByUsernameFail() { - // Expected - String username = "random@email.com"; - expectedException.expect(UsernameNotFoundException.class); - expectedException.expectMessage(Matchers.containsString(username)); - - // When - accountService.loadUserByUsername(username); + assertThrows(UsernameNotFoundException.class, () -> accountService.loadUserByUsername("random@email.com")); } } \ No newline at end of file diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseControllerTest.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseTest.java similarity index 82% rename from rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseControllerTest.java rename to rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseTest.java index 468266f..a772429 100644 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseControllerTest.java +++ b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/common/BaseTest.java @@ -1,8 +1,7 @@ package me.whiteship.demoinfleanrestapi.common; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Ignore; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Disabled; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; @@ -10,17 +9,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; -@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc @AutoConfigureRestDocs @Import(RestDocsConfiguration.class) @ActiveProfiles("test") -@Ignore -public class BaseControllerTest { +@Disabled +public class BaseTest { @Autowired protected MockMvc mockMvc; diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/configs/AuthServerConfigTest.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/configs/AuthServerConfigTest.java index 0d2e03d..8ff5f63 100644 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/configs/AuthServerConfigTest.java +++ b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/configs/AuthServerConfigTest.java @@ -1,23 +1,19 @@ package me.whiteship.demoinfleanrestapi.configs; -import me.whiteship.demoinfleanrestapi.accounts.Account; -import me.whiteship.demoinfleanrestapi.accounts.AccountRole; import me.whiteship.demoinfleanrestapi.accounts.AccountService; import me.whiteship.demoinfleanrestapi.common.AppProperties; -import me.whiteship.demoinfleanrestapi.common.BaseControllerTest; -import me.whiteship.demoinfleanrestapi.common.TestDescription; -import org.junit.Test; +import me.whiteship.demoinfleanrestapi.common.BaseTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Set; - import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -public class AuthServerConfigTest extends BaseControllerTest { +public class AuthServerConfigTest extends BaseTest { @Autowired AccountService accountService; @@ -26,7 +22,7 @@ public class AuthServerConfigTest extends BaseControllerTest { AppProperties appProperties; @Test - @TestDescription("인증 토큰을 발급 받는 테스트") + @DisplayName("인증 토큰을 발급 받는 테스트") public void getAuthToken() throws Exception { this.mockMvc.perform(post("/oauth/token") .with(httpBasic(appProperties.getClientId(), appProperties.getClientSecret())) diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/events/EventControllerTests.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/events/EventControllerTests.java index 8229230..3902bf2 100644 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/events/EventControllerTests.java +++ b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/events/EventControllerTests.java @@ -5,10 +5,10 @@ import me.whiteship.demoinfleanrestapi.accounts.AccountRole; import me.whiteship.demoinfleanrestapi.accounts.AccountService; import me.whiteship.demoinfleanrestapi.common.AppProperties; -import me.whiteship.demoinfleanrestapi.common.BaseControllerTest; -import me.whiteship.demoinfleanrestapi.common.TestDescription; -import org.junit.Before; -import org.junit.Test; +import me.whiteship.demoinfleanrestapi.common.BaseTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.MediaTypes; import org.springframework.http.HttpHeaders; @@ -30,7 +30,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -public class EventControllerTests extends BaseControllerTest { +public class EventControllerTests extends BaseTest { @Autowired EventRepository eventRepository; @@ -44,14 +44,14 @@ public class EventControllerTests extends BaseControllerTest { @Autowired AppProperties appProperties; - @Before + @BeforeEach public void setUp() { this.eventRepository.deleteAll(); this.accountRepository.deleteAll(); } @Test - @TestDescription("정상적으로 이벤트를 생성하는 테스트") + @DisplayName("정상적으로 이벤트를 생성하는 테스트") public void createEvent() throws Exception { EventDto event = EventDto.builder() .name("Spring") @@ -68,14 +68,14 @@ public void createEvent() throws Exception { mockMvc.perform(post("/api/events/") .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .accept(MediaTypes.HAL_JSON) .content(objectMapper.writeValueAsString(event))) .andDo(print()) .andExpect(status().isCreated()) .andExpect(jsonPath("id").exists()) .andExpect(header().exists(HttpHeaders.LOCATION)) - .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_JSON_UTF8_VALUE)) + .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_JSON_VALUE)) .andExpect(jsonPath("free").value(false)) .andExpect(jsonPath("offline").value(true)) .andExpect(jsonPath("eventStatus").value(EventStatus.DRAFT.name())) @@ -162,7 +162,7 @@ private Account createAccount() { } @Test - @TestDescription("입력 받을 수 없는 값을 사용한 경우에 에러가 발생하는 테스트") + @DisplayName("입력 받을 수 없는 값을 사용한 경우에 에러가 발생하는 테스트") public void createEvent_Bad_Request() throws Exception { Event event = Event.builder() .id(100) @@ -183,7 +183,7 @@ public void createEvent_Bad_Request() throws Exception { mockMvc.perform(post("/api/events/") .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .accept(MediaTypes.HAL_JSON) .content(objectMapper.writeValueAsString(event))) .andDo(print()) @@ -192,19 +192,19 @@ public void createEvent_Bad_Request() throws Exception { } @Test - @TestDescription("입력 값이 비어있는 경우에 에러가 발생하는 테스트") + @DisplayName("입력 값이 비어있는 경우에 에러가 발생하는 테스트") public void createEvent_Bad_Request_Empty_Input() throws Exception { EventDto eventDto = EventDto.builder().build(); this.mockMvc.perform(post("/api/events") .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andExpect(status().isBadRequest()); } @Test - @TestDescription("입력 값이 잘못된 경우에 에러가 발생하는 테스트") + @DisplayName("입력 값이 잘못된 경우에 에러가 발생하는 테스트") public void createEvent_Bad_Request_Wrong_Input() throws Exception { EventDto eventDto = EventDto.builder() .name("Spring") @@ -221,7 +221,7 @@ public void createEvent_Bad_Request_Wrong_Input() throws Exception { this.mockMvc.perform(post("/api/events") .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andDo(print()) .andExpect(status().isBadRequest()) @@ -233,7 +233,7 @@ public void createEvent_Bad_Request_Wrong_Input() throws Exception { } @Test - @TestDescription("30개의 이벤트를 10개씩 두번째 페이지 조회하기") + @DisplayName("30개의 이벤트를 10개씩 두번째 페이지 조회하기") public void queryEvents() throws Exception { // Given IntStream.range(0, 30).forEach(this::generateEvent); @@ -254,7 +254,7 @@ public void queryEvents() throws Exception { } @Test - @TestDescription("30개의 이벤트를 10개씩 두번째 페이지 조회하기") + @DisplayName("30개의 이벤트를 10개씩 두번째 페이지 조회하기") public void queryEventsWithAuthentication() throws Exception { // Given IntStream.range(0, 30).forEach(this::generateEvent); @@ -277,7 +277,7 @@ public void queryEventsWithAuthentication() throws Exception { } @Test - @TestDescription("기존의 이벤트를 하나 조죄하기") + @DisplayName("기존의 이벤트를 하나 조죄하기") public void getEvent() throws Exception { // Given Account account = this.createAccount(); @@ -295,7 +295,7 @@ public void getEvent() throws Exception { } @Test - @TestDescription("없는 이벤트는 조회했을 때 404 응답받기") + @DisplayName("없는 이벤트는 조회했을 때 404 응답받기") public void getEvent404() throws Exception { // When & Then this.mockMvc.perform(get("/api/events/11883")) @@ -303,7 +303,7 @@ public void getEvent404() throws Exception { } @Test - @TestDescription("이벤트를 정상적으로 수정하기") + @DisplayName("이벤트를 정상적으로 수정하기") public void updateEvent() throws Exception { // Given Account account = this.createAccount(); @@ -316,7 +316,7 @@ public void updateEvent() throws Exception { // When & Then this.mockMvc.perform(put("/api/events/{id}", event.getId()) .header(HttpHeaders.AUTHORIZATION, getBearerToken(false)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andDo(print()) .andExpect(status().isOk()) @@ -327,7 +327,7 @@ public void updateEvent() throws Exception { } @Test - @TestDescription("입력값이 비어있는 경우에 이벤트 수정 실패") + @DisplayName("입력값이 비어있는 경우에 이벤트 수정 실패") public void updateEvent400_Empty() throws Exception { // Given Event event = this.generateEvent(200); @@ -337,14 +337,14 @@ public void updateEvent400_Empty() throws Exception { // When & Then this.mockMvc.perform(put("/api/events/{id}", event.getId()) .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andDo(print()) .andExpect(status().isBadRequest()); } @Test - @TestDescription("입력값이 잘못된 경우에 이벤트 수정 실패") + @DisplayName("입력값이 잘못된 경우에 이벤트 수정 실패") public void updateEvent400_Wrong() throws Exception { // Given Event event = this.generateEvent(200); @@ -356,14 +356,14 @@ public void updateEvent400_Wrong() throws Exception { // When & Then this.mockMvc.perform(put("/api/events/{id}", event.getId()) .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andDo(print()) .andExpect(status().isBadRequest()); } @Test - @TestDescription("존재하지 않는 이벤트 수정 실패") + @DisplayName("존재하지 않는 이벤트 수정 실패") public void updateEvent404() throws Exception { // Given Event event = this.generateEvent(200); @@ -372,7 +372,7 @@ public void updateEvent404() throws Exception { // When & Then this.mockMvc.perform(put("/api/events/123123") .header(HttpHeaders.AUTHORIZATION, getBearerToken(true)) - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .content(this.objectMapper.writeValueAsString(eventDto))) .andDo(print()) .andExpect(status().isNotFound()); diff --git a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/index/IndexControllerTest.java b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/index/IndexControllerTest.java index 02491af..407ad33 100644 --- a/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/index/IndexControllerTest.java +++ b/rest-api-with-spring/src/test/java/me/whiteship/demoinfleanrestapi/index/IndexControllerTest.java @@ -1,13 +1,13 @@ package me.whiteship.demoinfleanrestapi.index; -import me.whiteship.demoinfleanrestapi.common.BaseControllerTest; -import org.junit.Test; +import me.whiteship.demoinfleanrestapi.common.BaseTest; +import org.junit.jupiter.api.Test; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -public class IndexControllerTest extends BaseControllerTest { +public class IndexControllerTest extends BaseTest { @Test public void index() throws Exception {