๐Ÿ’ Spring/Spring REST API

๐Ÿ’ Spring/Spring REST API

[HAEOAS] linkTo ๋ฉ”์†Œ๋“œ exception ๋ฐœ์ƒ

์ค‘๊ฐ„ ์ƒ๋žต... POST ์š”์ฒญ์œผ๋กœ ๋ณด๋‚ด๋ฉด,, POST http://localhost:8080/boards/1/pockets requestBody : { "title" : "pocket title" } ์•„๋ž˜ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋Œ€์ถฉ ๋ณด๋‹ˆ๊นŒ, PocketController์— addPocket ๋ฉ”์†Œ๋“œ์— linkTo๋ฅผ ์‹คํ–‰ํ•˜๋‹ค๊ฐ€ ์—๋Ÿฌ๊ฐ€ ๋‚œ ๊ฒƒ๊ฐ™๋‹ค. boardId๊ฐ’์„ ํ™•์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜๊ฐ’์ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค..? ๋ผ๊ณ  ๋œจ๋Š”๋ฐ ๋ญ” ๋ง์ด์ง€.. @PostMapping public ResponseEntity addPocket(@PathVariable Long boardId, @RequestBody PocketDto pocketDto) throws NotFoundException { System.out.println("boar..

๐Ÿ’ Spring/Spring REST API

7) [test] @JUnitParams ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง - ์Šคํ”„๋ง REST API

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ ์šฉ ๋๋Š”์ง€ ์‘๋‹ต ๋ฉ”์‹œ์ง€ ํ™•์ธ offline ๊ณผ free ๊ฐ’ ํ™•์ธ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ผ๋‹จ offline์€ location์— ๊ฐ’์ด ๋“ค์–ด์žˆ์œผ๋ฉด ์˜คํ”„๋ผ์ธ์ด๊ณ , ๊ฐ’์ด ์—†์œผ๋ฉด ์˜จ๋ผ์ธ์œผ๋กœ ์ง„ํ–‰์ด ๋œ๋‹ค. free๊ฐ’์€ basePrice์™€, MaxPrice๊ฐ€ ๋‘˜ ๋‹ค 0์ผ๋•Œ , free ์ด๋‹ค. Event.class ๋„๋ฉ”์ธ ํด๋ž˜์Šค์—๋‹ค๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ ์šฉ์‹œ์ผœ์ค€๋‹ค. public void update() { this.free = (basePrice == 0) && (maxPrice == 0); this.offline = location != null; } EventTests.class @Test public void testOffine() { // Given Event event = Event.builder() ...

๐Ÿ’ Spring/Spring REST API

6) [test] Bad_Request ์‘๋‹ต ๋ณธ๋ฌธ ๋งŒ๋“ค๊ธฐ - ์Šคํ”„๋ง REST API

์ด๋ฒˆ์— ํ•  ๊ฒƒ์€ Bad Request ์‘๋‹ต ๋ณธ๋ฌธ ๋งŒ๋“ค๊ธฐ ์ด๋‹ค. EventController ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, @PostMapping public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors) { //@Valid ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค๋ฉด, ์˜์กด์„ฑ ์ถ”๊ฐ€ : spring-boot-starter-validation ์„ ํ•ด์ค€๋‹ค. if (errors.hasErrors()) { return ResponseEntity.badRequest().build(); } eventValidator.validate(eventDto, errors); if (errors.hasErrors()) { return ResponseEntity.badReq..

๐Ÿ’ Spring/Spring REST API

5) [test] ์ž…๋ ฅ๊ฐ’ ์ œํ•œํ•˜๊ธฐ (๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์œผ๋กœ ๊ฒ€์‚ฌ) - ์Šคํ”„๋ง REST API

@Valid ์™€ BindingResult (๋˜๋Š” Errors) BindingResult ๋Š” ํ•ญ์ƒ @Valid ๋ฐ”๋กœ ๋‹ค์Œ ์ธ์ž๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•จ (์Šคํ”„๋ง MVC) @NotNull, @NotEmpty, @Min, @Max ... ์‚ฌ์šฉํ•ด์„œ ์ž…๋ ฅ๊ฐ’ ๋ฐ”์ธ๋”ฉ ํ• ๋•Œ ์—๋Ÿฌ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค ๋„๋ฉ”์ธ Validator ๋งŒ๋“ค๊ธฐ Validator ์ธํ„ฐํŽ˜์ด์Šค ์—†์ด ๋งŒ๋“ค์–ด๋„ ์ƒ๊ด€์—†๋‹ค. @Component public class EventValidator { public void validate(EventDto eventDto, Errors errors) { if (eventDto.getBasePrice() > eventDto.getMaxPrice() && eventDto.getMaxPrice() != 0) { errors.reject..

๐Ÿ’ Spring/Spring REST API

4) [test] ์ž…๋ ฅ๊ฐ’ ์ œํ•œํ•˜๊ธฐ (Bad_Request ๋ฐœ์ƒ) - ์Šคํ”„๋ง REST API

ํ…Œ์ŠคํŠธ ํ•  ๊ฒƒ ์ž…๋ ฅ๊ฐ’์œผ๋กœ ๋ˆ„๊ฐ€ id๋‚˜ eventStatus, offline, free ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ๊ฐ™์ด ์ฃผ๋ฉด? Bad_Request ๋ฐœ์ƒ (์ด๋ฒˆ ํ…Œ์ŠคํŠธ!) vs ๋ฐ›๊ธฐ๋กœ ํ•œ ๊ฐ’ ์ด์™ธ๋Š” ๋ฌด์‹œ ํ•ต์‹ฌ ์ฝ”๋“œ ObjectMapper ์ปค์Šคํ„ฐ๋งˆ์ด์ง• spring.jackson.deserialization.fail-on-unknown-properties = true // deserialization : ์—ญ์ง๋ ฌํ™”(JSON -> ๊ฐ์ฒด) ๋ฅผ ํ•˜๋Š”๋ฐ, unknown-properties๊ฐ€ ์žˆ์œผ๋ฉด -> fail-on ์‹คํŒจ๋ฅผ ๋˜์ง„๋‹ค.application.properties spring.jackson.deserialization.fail-on-unknown-properties=true #์™œ deserialization์ด๋ƒ๋ฉด, (Js..

๐Ÿ’ Spring/Spring REST API

3) [test] ์ž…๋ ฅ๊ฐ’ ์ œํ•œํ•˜๊ธฐ (๋ฌด์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•) - ์Šคํ”„๋ง REST API

ํ…Œ์ŠคํŠธ ํ•  ๊ฒƒ ์ž…๋ ฅ๊ฐ’์œผ๋กœ ๋ˆ„๊ฐ€ id๋‚˜ eventStatus, offline, free ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ๊ฐ™์ด ์ฃผ๋ฉด? Bad_Request ๋กœ ์‘๋‹ต vs ๋ฐ›๊ธฐ๋กœ ํ•œ ๊ฐ’ ์ด์™ธ๋Š” ๋ฌด์‹œ! (์ด๋ฒˆ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•) ์ž…๋ ฅ๊ฐ’ ์ œํ•œ id ๋˜๋Š” ์ž…๋ ฅ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋กœ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๋Š” ๊ฐ’๋“ค์€ ์ž…๋ ฅ ๋ฐ›์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค. EventDTO ์ ์šฉ DTO -> ๋„๋ฉ”์ธ ๊ฐ์ฒด๋กœ ๊ฐ’ ๋ณต์‚ฌ ModelMapper ์˜์กด์„ฑ ์ถ”๊ฐ€ org.modelmapper modelmapper 2.3.1 ๋นˆ์œผ๋กœ ๋“ฑ๋ก @Configuration ์•„๋ž˜์— @Bean public ModelMapper modelMapper(){ return new ModelMapper(); }ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋กœ ์ „ํ™˜ @WebMvcTest ๋นผ๊ณ  ๋‹ค์Œ ์• ๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ @SpringBootTest @Aut..

iseunghan
'๐Ÿ’ Spring/Spring REST API' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€ ๋ชฉ๋ก