-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Step1] 경로 찾기 - 지하철역 관리 #34
Changes from all commits
38c416e
1f12382
7ca8e2c
24830d1
5836bed
781e1ce
5755f3f
3d98742
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,38 @@ | ||||||
package atdd.station.Service; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
import atdd.station.domain.Station; | ||||||
import atdd.station.domain.dto.StationDto; | ||||||
import atdd.station.repository.StationRepository; | ||||||
import org.springframework.stereotype.Service; | ||||||
|
||||||
import javax.annotation.Resource; | ||||||
import java.util.List; | ||||||
import java.util.Optional; | ||||||
|
||||||
@Service("stationService") | ||||||
public class StationService | ||||||
{ | ||||||
@Resource(name = "stationRepository") | ||||||
private StationRepository stationRepository; | ||||||
|
||||||
public Station create(StationDto stationDto) | ||||||
{ | ||||||
return stationRepository.save(stationDto.toEntity()); | ||||||
} | ||||||
|
||||||
public List<Station> list() | ||||||
{ | ||||||
List<Station> returnList = stationRepository.findAll(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. List, Set 등 자료구조를 지칭하는 단어를 클래스나 변수이름으로 사용하는 것을 지양하고 있습니다. |
||||||
return returnList; | ||||||
} | ||||||
|
||||||
public Optional<Station> findById(long id) | ||||||
{ | ||||||
return stationRepository.findById(id); | ||||||
} | ||||||
|
||||||
public void deleteStationById(long id) | ||||||
{ | ||||||
stationRepository.deleteById(id); | ||||||
} | ||||||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,65 @@ | ||||||||||||
package atdd.station.controller; | ||||||||||||
|
||||||||||||
import atdd.station.Service.StationService; | ||||||||||||
import atdd.station.domain.Station; | ||||||||||||
import atdd.station.domain.dto.StationDto; | ||||||||||||
import org.springframework.http.HttpHeaders; | ||||||||||||
import org.springframework.http.HttpStatus; | ||||||||||||
import org.springframework.http.ResponseEntity; | ||||||||||||
import org.springframework.web.bind.annotation.*; | ||||||||||||
|
||||||||||||
import javax.annotation.Resource; | ||||||||||||
import java.net.URI; | ||||||||||||
import java.util.List; | ||||||||||||
import java.util.Optional; | ||||||||||||
|
||||||||||||
/* | ||||||||||||
step1 : 지하철역 관리 API 만들기 | ||||||||||||
*/ | ||||||||||||
@RestController | ||||||||||||
@RequestMapping(value = "/stations", produces = "application/json") | ||||||||||||
public class StationController | ||||||||||||
{ | ||||||||||||
@Resource(name = "stationService") | ||||||||||||
private StationService stationService; | ||||||||||||
/* | ||||||||||||
1. 지하철역 등록 | ||||||||||||
*/ | ||||||||||||
Comment on lines
+25
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 주석보다는 코드로 의도를 드러내는 것을 선호하는 편입니다 ㅎ; |
||||||||||||
@PostMapping("/create") | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. REST API 설계시에,
stations URI에 POST 요청을 보내는 것만으로도 생성의 의미를 표현할 수 있습니다. POST와 PUT 사용에 대해서는 해석의 여지가 있습니다.
이 경우엔, PUT을 사용하여 리소스를 생성할 경우, 요청하는 쪽에서 ID를 알고 있어야 합니다. |
||||||||||||
public ResponseEntity<Station> createStations(@RequestBody StationDto stationDto) | ||||||||||||
{ | ||||||||||||
Station createdStation = stationService.create(stationDto); | ||||||||||||
HttpHeaders headers = new HttpHeaders(); | ||||||||||||
headers.setLocation(URI.create("/stations/list" + createdStation.getId())); | ||||||||||||
ResponseEntity<Station> returnEntity = new ResponseEntity<>(createdStation, headers, HttpStatus.CREATED); | ||||||||||||
return returnEntity; | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
public static BodyBuilder created(URI location) {
BodyBuilder builder = status(HttpStatus.CREATED);
return builder.location(location);
}
|
||||||||||||
} | ||||||||||||
/* | ||||||||||||
2. 지하철역 목록 조회 | ||||||||||||
*/ | ||||||||||||
@GetMapping("/list") | ||||||||||||
public ResponseEntity list() | ||||||||||||
{ | ||||||||||||
List<Station> stationList = stationService.list(); | ||||||||||||
ResponseEntity returnEntity = new ResponseEntity(stationList, HttpStatus.OK); | ||||||||||||
return returnEntity; | ||||||||||||
} | ||||||||||||
/* | ||||||||||||
3. 지하철역 조회 | ||||||||||||
*/ | ||||||||||||
@GetMapping("/detail/{id}") | ||||||||||||
public ResponseEntity detailById(@PathVariable long id) | ||||||||||||
{ | ||||||||||||
Optional<Station> detailStation = stationService.findById(id); | ||||||||||||
ResponseEntity returnEntity = new ResponseEntity(detailStation, HttpStatus.OK); | ||||||||||||
return returnEntity; | ||||||||||||
} | ||||||||||||
/* | ||||||||||||
4. 지하철역 삭제 | ||||||||||||
*/ | ||||||||||||
@DeleteMapping("/delete/{id}") | ||||||||||||
public void deleteStation(@PathVariable long id) | ||||||||||||
{ | ||||||||||||
stationService.deleteStationById(id); | ||||||||||||
} | ||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package atdd.station.domain; | ||
|
||
import lombok.*; | ||
|
||
import javax.persistence.*; | ||
|
||
@NoArgsConstructor | ||
@Getter | ||
@Entity | ||
public class Station | ||
{ | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
private long id; | ||
|
||
@Column(length = 20, nullable = false) | ||
private String name; | ||
|
||
@Builder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
public Station(String name) | ||
{ | ||
this.name = name; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package atdd.station.domain.dto; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dto는 presentation layer에 해당하니 controller 하위 패키지에 있는 것은 어떨까요 |
||
|
||
import atdd.station.domain.Station; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
public class StationDto | ||
{ | ||
private String name; | ||
|
||
public Station toEntity() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 추가적으로 아래 링크들에서 DTO 관련 논의들이 있으니 참고해보세요. |
||
{ | ||
return Station.builder().name(name).build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package atdd.station.repository; | ||
|
||
import atdd.station.domain.Station; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface StationRepository extends JpaRepository<Station, Long> {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
spring: | ||
h2: | ||
console: | ||
enabled: true | ||
datasource: | ||
driver-class-name: org.h2.Driver | ||
url: jdbc:h2:mem:testdb | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package atdd.station.controller; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.test.annotation.DirtiesContext; | ||
import org.springframework.test.web.reactive.server.WebTestClient; | ||
import reactor.core.publisher.Mono; | ||
|
||
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) | ||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | ||
@AutoConfigureWebTestClient | ||
public class StationAcceptanceTest | ||
{ | ||
private static final Logger logger = LoggerFactory.getLogger(StationAcceptanceTest.class); | ||
|
||
private final String STATIOIN_NAME = "강남역"; | ||
private final String BASE_URL = "/stations"; | ||
private final int TEST_ID = 1; | ||
|
||
@Autowired | ||
private WebTestClient webTestClient; | ||
|
||
@Test | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. junit5의 경우 |
||
public void createStation() | ||
{ | ||
String inputJson = "{\"name\":\""+ this.STATIOIN_NAME +"\"}"; | ||
|
||
webTestClient.post().uri(BASE_URL + "/create") | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.body(Mono.just(inputJson), String.class) | ||
.exchange() | ||
.expectStatus().isCreated() | ||
.expectHeader().contentType(MediaType.APPLICATION_JSON) | ||
.expectHeader().exists("Location") | ||
.expectBody().jsonPath("$.name").isEqualTo(this.STATIOIN_NAME); | ||
} | ||
|
||
@Test | ||
public void list() | ||
{ | ||
testCreateStation(STATIOIN_NAME); | ||
|
||
webTestClient.get().uri(BASE_URL + "/list") | ||
.exchange() | ||
.expectStatus().isOk() | ||
.expectHeader().contentType(MediaType.APPLICATION_JSON) | ||
.expectBody().jsonPath("$.[0].name").isEqualTo(STATIOIN_NAME); | ||
} | ||
|
||
@Test | ||
public void detailById() | ||
{ | ||
testCreateStation(STATIOIN_NAME); | ||
|
||
webTestClient.get().uri(BASE_URL + "/detail/" + TEST_ID) | ||
.exchange() | ||
.expectStatus().isOk() | ||
.expectHeader().contentType(MediaType.APPLICATION_JSON) | ||
.expectBody().jsonPath("$.name").isEqualTo(STATIOIN_NAME); | ||
|
||
} | ||
|
||
@Test | ||
public void deleteStation() | ||
{ | ||
testCreateStation(STATIOIN_NAME); | ||
|
||
webTestClient.delete().uri(BASE_URL + "/delete/" + TEST_ID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ID가 반드시 1임을 어떻게 보장할 수 있을까요 |
||
.exchange() | ||
.expectStatus().isOk(); | ||
} | ||
|
||
|
||
public void testCreateStation(String stationName) | ||
{ | ||
String inputJson = "{\"name\":\""+ this.STATIOIN_NAME +"\"}"; | ||
Comment on lines
+79
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메서드를 통해 인자로 받는다면 inputJson에서 이 값을 활용하여야 하지 않을까요 |
||
|
||
webTestClient.post().uri(BASE_URL + "/create") | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.body(Mono.just(inputJson), String.class) | ||
.exchange() | ||
.expectStatus().isCreated() | ||
.expectHeader().contentType(MediaType.APPLICATION_JSON) | ||
.expectHeader().exists("Location") | ||
.expectBody().jsonPath("$.name").isEqualTo(stationName); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍