Skip to content
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

E2e step2 #877

Open
wants to merge 5 commits into
base: jaejeong1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ dependencies {
// log
implementation 'net.rakugakibox.spring.boot:logback-access-spring-boot-starter:2.7.1'

// guava
implementation 'com.google.guava:guava:32.1.1-jre'

// lombok
compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.rest-assured:rest-assured:4.5.1'

Expand Down
28 changes: 28 additions & 0 deletions src/main/java/subway/line/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package subway.line;

import lombok.Getter;

import javax.persistence.*;

@Entity
@Getter
public class Line {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String color;

public Line() {}

public Line(String name, String color) {
this.name = name;
this.color = color;
}

public void update(String name, String color) {
this.name = name;
this.color = color;
}
}
44 changes: 44 additions & 0 deletions src/main/java/subway/line/LineController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package subway.line;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.util.List;

@RestController
public class LineController {
private final LineService lineService;

public LineController(LineService lineService) {
this.lineService = lineService;
}

@GetMapping("/lines")
public ResponseEntity<List<LineResponse>> showLines() {
return ResponseEntity.ok().body(lineService.findAllLines());
}

@PostMapping("/lines")
public ResponseEntity<LineResponse> createLine(@RequestBody LineRequest lineRequest) {
LineResponse line = lineService.saveLine(lineRequest);
return ResponseEntity.created(URI.create("/lines/" + line.getId())).body(line);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미션 요구사항과 다른 스펙으로 구현되어 있어요. 😭
LineController의 다른 부분들도 미션에서 요구하는 스펙에 맞게 변경해 주세요!
image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

가장 중요한 요구사항 구현에 미스가 있었군요.. 참고해서 수정해보겠습니다! 감사합니다 :)


@GetMapping("/lines/{id}")
public ResponseEntity<LineResponse> showLine(@PathVariable Long id) {
return ResponseEntity.ok().body(lineService.findLineById(id));
}

@PutMapping("/lines/{id}")
public ResponseEntity<Void> updateLine(@PathVariable Long id, @RequestBody LineRequest lineRequest) {
lineService.updateLine(id, lineRequest);
return ResponseEntity.ok().build();
}

@DeleteMapping("/lines/{id}")
public ResponseEntity<Void> deleteLine(@PathVariable Long id) {
lineService.deleteLineById(id);
return ResponseEntity.noContent().build();
}
}
6 changes: 6 additions & 0 deletions src/main/java/subway/line/LineRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package subway.line;

import org.springframework.data.jpa.repository.JpaRepository;

public interface LineRepository extends JpaRepository<Line, Long> {
}
9 changes: 9 additions & 0 deletions src/main/java/subway/line/LineRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package subway.line;

import lombok.Getter;

@Getter
public class LineRequest {
private String name;
private String color;
}
19 changes: 19 additions & 0 deletions src/main/java/subway/line/LineResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package subway.line;

import lombok.Getter;
import subway.station.Station;

import java.util.List;

@Getter
public class LineResponse {
private Long id;
private String name;
private String color;

public LineResponse(Long id, String name, String color) {
this.id = id;
this.name = name;
this.color = color;
}
}
52 changes: 52 additions & 0 deletions src/main/java/subway/line/LineService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package subway.line;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
public class LineService {
private LineRepository lineRepository;

public LineService(LineRepository lineRepository) {
this.lineRepository = lineRepository;
}

@Transactional
public LineResponse saveLine(LineRequest lineRequest) {
Line line = lineRepository.save(new Line(lineRequest.getName(), lineRequest.getColor()));
return createLineResponse(line);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API 스펙을 미션 요구사항에 맞게 변경하면 아마 LineService의 로직들이 조금 더 복잡해질 거예요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder 패턴 적용해 Line 엔티티 생성 과정의 유연성을 확보했습니다!


public List<LineResponse> findAllLines() {
return lineRepository.findAll().stream()
.map(this::createLineResponse)
.collect(Collectors.toList());
}

public LineResponse findLineById(Long id) {
return createLineResponse(lineRepository.findById(id).orElseThrow(IllegalArgumentException::new));
}

@Transactional
public void updateLine(Long id, LineRequest lineRequest) {
Line line = lineRepository.findById(id).orElseThrow(IllegalArgumentException::new);
line.update(lineRequest.getName(), lineRequest.getColor());
}

@Transactional
public void deleteLineById(Long id) {
lineRepository.deleteById(id);
}

private LineResponse createLineResponse(Line line) {
return new LineResponse(
line.getId(),
line.getName(),
line.getColor()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package subway;
package subway.station;

import subway.line.Line;

import javax.persistence.*;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package subway;
package subway.station;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package subway;
package subway.station;

import org.springframework.data.jpa.repository.JpaRepository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package subway;
package subway.station;

public class StationRequest {
private String name;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package subway;
package subway.station;

public class StationResponse {
private Long id;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package subway;
package subway.station;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down
31 changes: 31 additions & 0 deletions src/test/java/subway/AcceptanceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package subway;

import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.ActiveProfiles;

import static io.restassured.RestAssured.UNDEFINED_PORT;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("acceptance")
public abstract class AcceptanceTest {

@LocalServerPort
protected int port;

@Autowired
private DatabaseCleanup databaseCleanup;

@BeforeEach
void setUp() {
if (RestAssured.port == UNDEFINED_PORT) {
RestAssured.port = port;
databaseCleanup.afterPropertiesSet();
}
databaseCleanup.execute();
}
}
45 changes: 45 additions & 0 deletions src/test/java/subway/DatabaseCleanup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package subway;

import com.google.common.base.CaseFormat;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Profile("acceptance")
public class DatabaseCleanup implements InitializingBean{
@PersistenceContext
private EntityManager entityManager;
private List<String> tableNames;
@Override
public void afterPropertiesSet() {
tableNames = entityManager.getMetamodel().getEntities().stream()
.filter(e -> e.getJavaType().getAnnotation(Entity.class) != null)
.map(e -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, e.getName()))
.collect(Collectors.toList());
}

@Transactional
public void execute() {
// 쓰기 지연 저장소에 남은 SQL을 마저 수행
entityManager.flush();
// 연관 관계 맵핑된 테이블이 있는 경우 참조 무결성을 해제해줘야 Trancate 가능
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
Comment on lines +29 to +34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanup 잘 만들어 주셨네요. 👍


for (String tableName : tableNames) {
// 테이블 이름 순회하며 Trancate SQL 수행
entityManager.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate();
// 테이블의 내부가 지워지면 그 다음부터는 ID값을 다시 1부터 시작할 수 있도록 기본 값 초기화
entityManager.createNativeQuery("ALTER TABLE " + tableName + " ALTER COLUMN "
+ "ID RESTART WITH 1").executeUpdate();
}
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
}
}
9 changes: 9 additions & 0 deletions src/test/java/subway/HttpRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ public static ExtractableResponse<Response> sendPostRequest(String path, Map<Str
.extract();
}

public static ExtractableResponse<Response> sendPutRequest(String path, Map<String, String> params) {
return RestAssured.given().log().all()
.body(params)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.when().put(path)
.then().log().all()
.extract();
}

public static ExtractableResponse<Response> sendDeleteRequest(String path) {
return RestAssured.given().log().all()
.when().delete(path)
Expand Down
Loading