From 62a03e6e12b1fa0dc2a707b9c586f29a2019f264 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 18 May 2023 15:19:16 +0900 Subject: [PATCH 01/41] =?UTF-8?q?fix=20:=20=EC=A0=9C=EC=9D=BC=20=EC=95=9E?= =?UTF-8?q?=EC=9D=98=20Section=EC=97=90=20=EC=97=AD=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 상황 A -> B -> C 에서 A -> K 를 추가할 경우 exception 발생 --- src/main/java/subway/domain/Line.java | 11 +++++++ src/main/java/subway/domain/Section.java | 17 ++++++++++ src/test/java/subway/domain/LineTest.java | 40 +++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/Line.java index d262da06c..b77b59375 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/Line.java @@ -54,12 +54,23 @@ public void add(Section newSection) { } final Section targetSection = starter.findPreSectionOnAdd(newSection); + final Section sameStartSection = starter.findSameSectionOnAdd(newSection); if (canExchangeStarter(targetSection)) { + if (starter.isLinked(newSection)) { exchangeStarterOnAdd(newSection); return; } + + if (sameStartSection != null) { + newSection.updateNextSection(starter); + starter.updateSectionOnAdd(newSection); + starter = newSection; + return; + } + + throw new IllegalArgumentException("해당 섹션은 현재 Line에 추가할 수 없습니다."); } diff --git a/src/main/java/subway/domain/Section.java b/src/main/java/subway/domain/Section.java index 75ae52642..01203fc91 100644 --- a/src/main/java/subway/domain/Section.java +++ b/src/main/java/subway/domain/Section.java @@ -31,6 +31,19 @@ public Section findPreSectionOnAdd(final Section newSection) { return null; } + public Section findSameSectionOnAdd(final Section newSection) { + Section current = this; + + while (current != null) { + if (current.stations.isSameCurrent(newSection.stations.getCurrent())) { + return current; + } + current = current.to; + } + + return null; + } + public void addNext(final Section newSection) { Section current = findPreSectionOnAdd(newSection); @@ -57,6 +70,10 @@ private void addIntermediate(final Section newSection, final Section current) { newSection.to.stations.updateStationOnAdd(newSection.stations); } + public void updateSectionOnAdd(final Section newSection) { + stations.updateStationOnAdd(newSection.stations); + } + public boolean isLinked(final Section other) { return other.stations.isLinked(this.stations); } diff --git a/src/test/java/subway/domain/LineTest.java b/src/test/java/subway/domain/LineTest.java index 0d8aefc5a..c2041019d 100644 --- a/src/test/java/subway/domain/LineTest.java +++ b/src/test/java/subway/domain/LineTest.java @@ -76,6 +76,46 @@ void test_add_intermediate() throws Exception { assertEquals(section3.getTo(), 새로운_섹션); } + /** + * 기존 : `A` -> B -> C -> D -> E + * 추가 : A -> K + * 결론 : `A` -> K -> B -> C -> D -> E + */ + @Test + @DisplayName("add() : Line의 중간에 새로운 섹션을 추가할 수 있다.") + void test_add_intermediate2() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 헤드_섹션 = new Section(stations1); + + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + final Section section4 = new Section(stations4); + + final Line line = new Line(1L, "2호선", List.of(헤드_섹션, section2, section3, section4)); + + final Station current = new Station("A"); + final Station next = new Station("K"); + + final Stations 새로운_stations = new Stations(current, next, 2); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when + line.add(새로운_섹션); + + //then + assertAll( + () -> assertEquals(헤드_섹션.getTo(), section2), + () -> assertEquals(새로운_섹션.getTo(), 헤드_섹션), + () -> assertEquals(3, 헤드_섹션.getStations().getDistance()) + ); + } + /** * 기존 : A -> B -> C * 추가 : Z -> A From 752ed20eb2f8450596b01d9e26e551a23693a589 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Fri, 19 May 2023 14:08:18 +0900 Subject: [PATCH 02/41] =?UTF-8?q?refactor=20:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9D=B4=20=EC=99=B8=EB=B6=80=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=EC=97=90=20=EB=B0=94=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=ED=95=98=EC=A7=80=20=EC=95=8A=EA=B3=A0=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EC=97=90=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=ED=95=98=EB=A9=B4=EC=84=9C=20=EC=B5=9C?= =?UTF-8?q?=EB=8B=A8=20=EA=B2=BD=EB=A1=9C=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/domain/JgraphtRouteFinder.java | 70 +++++++++++++++++++ src/main/java/subway/domain/Route.java | 66 ++--------------- src/main/java/subway/domain/RouteFinder.java | 10 +++ .../subway/service/RouteQueryService.java | 7 +- src/test/java/subway/domain/RouteTest.java | 24 +++---- 5 files changed, 102 insertions(+), 75 deletions(-) create mode 100644 src/main/java/subway/domain/JgraphtRouteFinder.java create mode 100644 src/main/java/subway/domain/RouteFinder.java diff --git a/src/main/java/subway/domain/JgraphtRouteFinder.java b/src/main/java/subway/domain/JgraphtRouteFinder.java new file mode 100644 index 000000000..0aa33623d --- /dev/null +++ b/src/main/java/subway/domain/JgraphtRouteFinder.java @@ -0,0 +1,70 @@ +package subway.domain; + +import org.jgrapht.Graph; +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.DefaultWeightedEdge; +import org.jgrapht.graph.WeightedMultigraph; + +import java.util.List; + +public class JgraphtRouteFinder implements RouteFinder { + + private final DijkstraShortestPath dijkstraGraph; + + public JgraphtRouteFinder(final List lines) { + Graph graph + = new WeightedMultigraph<>(DefaultWeightedEdge.class); + + for (final Line line : lines) { + final List
sections = line.getSections(); + makeGraphFromSections(graph, sections); + } + + dijkstraGraph = new DijkstraShortestPath<>(graph); + } + + private void makeGraphFromSections( + final Graph graph, + final List
sections + ) { + for (final Section section : sections) { + final Stations stations = section.getStations(); + + final String startStation = stations.getCurrent().getName(); + final String endStation = stations.getNext().getName(); + final int distance = stations.getDistance(); + + addVertex(graph, startStation, endStation); + addEdge(graph, startStation, endStation, distance); + } + } + + private void addVertex( + final Graph graph, + final String startStation, + final String endStation + ) { + graph.addVertex(startStation); + graph.addVertex(endStation); + } + + private void addEdge( + final Graph graph, final String startStation, + final String endStation, final int distance + ) { + graph.setEdgeWeight( + graph.addEdge(startStation, endStation), distance); + graph.setEdgeWeight( + graph.addEdge(endStation, startStation), distance); + } + + @Override + public List findShortestRoute(final String startStation, final String endStation) { + return dijkstraGraph.getPath(startStation, endStation).getVertexList(); + } + + @Override + public Distance findShortestRouteDistance(final String startStation, final String endStation) { + return new Distance((int) dijkstraGraph.getPathWeight(startStation, endStation)); + } +} diff --git a/src/main/java/subway/domain/Route.java b/src/main/java/subway/domain/Route.java index 06880f1de..35db3c3d1 100644 --- a/src/main/java/subway/domain/Route.java +++ b/src/main/java/subway/domain/Route.java @@ -1,74 +1,20 @@ package subway.domain; -import org.jgrapht.Graph; -import org.jgrapht.alg.shortestpath.DijkstraShortestPath; -import org.jgrapht.graph.DefaultWeightedEdge; -import org.jgrapht.graph.WeightedMultigraph; - import java.util.List; public class Route { - private final DijkstraShortestPath dijkstraGraph; + private final RouteFinder routeFinder; public Route(final List lines) { - Graph graph - = new WeightedMultigraph<>(DefaultWeightedEdge.class); - - for (final Line line : lines) { - final List
sections = line.getSections(); - makeGraphFromSections(graph, sections); - } - - dijkstraGraph = new DijkstraShortestPath<>(graph); - } - - private void makeGraphFromSections( - final Graph graph, - final List
sections - ) { - for (final Section section : sections) { - final Stations stations = section.getStations(); - - final String startStation = stations.getCurrent().getName(); - final String endStation = stations.getNext().getName(); - final int distance = stations.getDistance(); - - addVertex(graph, startStation, endStation); - addEdge(graph, startStation, endStation, distance); - } - } - - private void addVertex( - final Graph graph, - final String startStation, - final String endStation - ) { - graph.addVertex(startStation); - graph.addVertex(endStation); - } - - private void addEdge( - final Graph graph, final String startStation, - final String endStation, final int distance - ) { - graph.setEdgeWeight( - graph.addEdge(startStation, endStation), distance); - graph.setEdgeWeight( - graph.addEdge(endStation, startStation), distance); + this.routeFinder = new JgraphtRouteFinder(lines); } - public List findShortestRoute( - final String startStation, - final String endStation - ) { - return dijkstraGraph.getPath(startStation, endStation).getVertexList(); + public List findShortestRoute(final String startStation, final String endStation) { + return routeFinder.findShortestRoute(startStation, endStation); } - public int findShortestRouteDistance( - final String startStation, - final String endStation - ) { - return (int) dijkstraGraph.getPathWeight(startStation, endStation); + public Distance findShortestRouteDistance(final String startStation, final String endStation) { + return routeFinder.findShortestRouteDistance(startStation, endStation); } } diff --git a/src/main/java/subway/domain/RouteFinder.java b/src/main/java/subway/domain/RouteFinder.java new file mode 100644 index 000000000..56d3f1b52 --- /dev/null +++ b/src/main/java/subway/domain/RouteFinder.java @@ -0,0 +1,10 @@ +package subway.domain; + +import java.util.List; + +public interface RouteFinder { + + List findShortestRoute(final String startStation, final String endStation); + + Distance findShortestRouteDistance(final String startStation, final String endStation); +} diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 6642efcbe..9d4f8430d 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -41,8 +41,9 @@ public int searchShortestDistance(final ShortestRouteRequest shortestRouteReques final Route route = new Route(lines); return route.findShortestRouteDistance( - shortestRouteRequest.getStartStation(), - shortestRouteRequest.getEndStation() - ); + shortestRouteRequest.getStartStation(), + shortestRouteRequest.getEndStation()) + .getValue(); } + } diff --git a/src/test/java/subway/domain/RouteTest.java b/src/test/java/subway/domain/RouteTest.java index 8d21d190c..ea32b4593 100644 --- a/src/test/java/subway/domain/RouteTest.java +++ b/src/test/java/subway/domain/RouteTest.java @@ -17,12 +17,12 @@ class RouteTest { /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | + * 11 5 + * F -- G -- H + * 4 | | 4 + * | | * A -- B -- C -- D - * 1 2 3 + * 1 2 3 */ @ParameterizedTest @@ -71,12 +71,12 @@ static Stream findShortestRoute() { } /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | + * 11 5 + * F -- G -- H + * 4 | | 4 + * | | * A -- B -- C -- D - * 1 2 3 + * 1 2 3 */ @ParameterizedTest @MethodSource("findShortestRouteDistance") @@ -92,10 +92,10 @@ void test_findShortestRoutePrice( final Route route = new Route(lines); //when - final double shortestRouteDistance = route.findShortestRouteDistance(start, end); + final Distance shortestRouteDistance = route.findShortestRouteDistance(start, end); //then - assertEquals(distance, shortestRouteDistance); + assertEquals(distance, shortestRouteDistance.getValue()); } static Stream findShortestRouteDistance() { From 6e9cf737b0b9a60d8ee342c4392a1a3cbd6c07bd Mon Sep 17 00:00:00 2001 From: java-saeng Date: Fri, 19 May 2023 21:00:13 +0900 Subject: [PATCH 03/41] =?UTF-8?q?feat=20:=20=ED=95=98=EB=82=98=EC=9D=98=20?= =?UTF-8?q?yml=20=EC=95=88=EC=97=90=20=EC=97=AC=EB=9F=AC=20profile=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=ED=95=B4=EB=B3=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-test.yml | 45 +++++++++++++++++++ .../subway/yml/ProfileActiveFirstTest.java | 26 +++++++++++ .../subway/yml/ProfileActiveSecondTest.java | 26 +++++++++++ .../subway/yml/ProfileActiveThirdTest.java | 26 +++++++++++ src/test/resources/application.yml | 4 -- 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/application-test.yml create mode 100644 src/test/java/subway/yml/ProfileActiveFirstTest.java create mode 100644 src/test/java/subway/yml/ProfileActiveSecondTest.java create mode 100644 src/test/java/subway/yml/ProfileActiveThirdTest.java delete mode 100644 src/test/resources/application.yml diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 000000000..fd2c8d374 --- /dev/null +++ b/src/main/resources/application-test.yml @@ -0,0 +1,45 @@ +spring: + datasource: + url: jdbc:h2:mem:first + driver-class-name: org.h2.Driver + username: + password: + config: + activate: + on-profile: first + sql: + init: + mode: never + +--- +spring: + datasource: + url: jdbc:h2:mem:second + driver-class-name: org.h2.Driver + username: + password: + config: + activate: + on-profile: second + sql: + init: + mode: never + +--- + +spring: + datasource: + url: jdbc:h2:mem:third + driver-class-name: org.h2.Driver + username: + password: + config: + activate: + on-profile: third + sql: + init: + mode: never + profiles: + active: + +--- diff --git a/src/test/java/subway/yml/ProfileActiveFirstTest.java b/src/test/java/subway/yml/ProfileActiveFirstTest.java new file mode 100644 index 000000000..3c918223c --- /dev/null +++ b/src/test/java/subway/yml/ProfileActiveFirstTest.java @@ -0,0 +1,26 @@ +package subway.yml; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import javax.sql.DataSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +@ActiveProfiles({"test", "first"}) +public class ProfileActiveFirstTest { + + @Autowired + private DataSource dataSource; + + @Test + void test_first() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:first"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } +} diff --git a/src/test/java/subway/yml/ProfileActiveSecondTest.java b/src/test/java/subway/yml/ProfileActiveSecondTest.java new file mode 100644 index 000000000..db38b783f --- /dev/null +++ b/src/test/java/subway/yml/ProfileActiveSecondTest.java @@ -0,0 +1,26 @@ +package subway.yml; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import javax.sql.DataSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +@ActiveProfiles({"second", "test"}) +public class ProfileActiveSecondTest { + + @Autowired + private DataSource dataSource; + + @Test + void test_default1() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:second"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } +} diff --git a/src/test/java/subway/yml/ProfileActiveThirdTest.java b/src/test/java/subway/yml/ProfileActiveThirdTest.java new file mode 100644 index 000000000..a578257e2 --- /dev/null +++ b/src/test/java/subway/yml/ProfileActiveThirdTest.java @@ -0,0 +1,26 @@ +package subway.yml; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import javax.sql.DataSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +@ActiveProfiles({"third", "test"}) +public class ProfileActiveThirdTest { + + @Autowired + private DataSource dataSource; + + @Test + void test_third() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:third"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml deleted file mode 100644 index 273a4b14c..000000000 --- a/src/test/resources/application.yml +++ /dev/null @@ -1,4 +0,0 @@ -spring: - datasource: - url: jdbc:h2:mem:testdb;MODE=MySQL - driver-class-name: org.h2.Driver From f9eebfc1b397b00496cdfe36570c8808a736193d Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sat, 20 May 2023 21:50:20 +0900 Subject: [PATCH 04/41] =?UTF-8?q?feat=20:=20=EC=B5=9C=EC=86=8C=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=ED=95=A0=20=EB=95=8C,=20Section=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/domain/EdgeSection.java | 39 ++++++++++++++++ .../subway/domain/JgraphtRouteFinder.java | 41 ++++++++++------- src/main/java/subway/domain/Route.java | 4 ++ src/main/java/subway/domain/RouteFinder.java | 2 + src/test/java/subway/domain/RouteTest.java | 44 +++++++++++++++++++ 5 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 src/main/java/subway/domain/EdgeSection.java diff --git a/src/main/java/subway/domain/EdgeSection.java b/src/main/java/subway/domain/EdgeSection.java new file mode 100644 index 000000000..f6a87c288 --- /dev/null +++ b/src/main/java/subway/domain/EdgeSection.java @@ -0,0 +1,39 @@ +package subway.domain; + +import org.jgrapht.graph.DefaultWeightedEdge; + +public class EdgeSection extends DefaultWeightedEdge { + + private final String startStation; + private final String endStation; + private final int distance; + private final String lineName; + + public EdgeSection( + final String startStation, + final String endStation, + final int distance, + final String lineName + ) { + this.startStation = startStation; + this.endStation = endStation; + this.distance = distance; + this.lineName = lineName; + } + + public String getStartStation() { + return startStation; + } + + public String getEndStation() { + return endStation; + } + + public String getLineName() { + return lineName; + } + + public int getDistance() { + return distance; + } +} diff --git a/src/main/java/subway/domain/JgraphtRouteFinder.java b/src/main/java/subway/domain/JgraphtRouteFinder.java index 0aa33623d..f8da087c1 100644 --- a/src/main/java/subway/domain/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/JgraphtRouteFinder.java @@ -2,31 +2,33 @@ import org.jgrapht.Graph; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; -import org.jgrapht.graph.DefaultWeightedEdge; import org.jgrapht.graph.WeightedMultigraph; import java.util.List; public class JgraphtRouteFinder implements RouteFinder { - private final DijkstraShortestPath dijkstraGraph; + private final DijkstraShortestPath dijkstraGraph; public JgraphtRouteFinder(final List lines) { - Graph graph - = new WeightedMultigraph<>(DefaultWeightedEdge.class); + Graph graph + = new WeightedMultigraph<>(EdgeSection.class); for (final Line line : lines) { final List
sections = line.getSections(); - makeGraphFromSections(graph, sections); + makeGraphFromSections(graph, line); } dijkstraGraph = new DijkstraShortestPath<>(graph); } private void makeGraphFromSections( - final Graph graph, - final List
sections + final Graph graph, + final Line line ) { + + final List
sections = line.getSections(); + for (final Section section : sections) { final Stations stations = section.getStations(); @@ -35,12 +37,12 @@ private void makeGraphFromSections( final int distance = stations.getDistance(); addVertex(graph, startStation, endStation); - addEdge(graph, startStation, endStation, distance); + addEdge(graph, startStation, endStation, distance, line.getName()); } } private void addVertex( - final Graph graph, + final Graph graph, final String startStation, final String endStation ) { @@ -49,13 +51,17 @@ private void addVertex( } private void addEdge( - final Graph graph, final String startStation, - final String endStation, final int distance + final Graph graph, final String startStation, + final String endStation, final int distance, final String lineName ) { - graph.setEdgeWeight( - graph.addEdge(startStation, endStation), distance); - graph.setEdgeWeight( - graph.addEdge(endStation, startStation), distance); + final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); + final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); + + graph.addEdge(startStation, endStation, start); + graph.addEdge(endStation, startStation, end); + + graph.setEdgeWeight(start, distance); + graph.setEdgeWeight(end, distance); } @Override @@ -67,4 +73,9 @@ public List findShortestRoute(final String startStation, final String en public Distance findShortestRouteDistance(final String startStation, final String endStation) { return new Distance((int) dijkstraGraph.getPathWeight(startStation, endStation)); } + + @Override + public List findShortestRouteSections(final String startStation, final String endStation) { + return dijkstraGraph.getPath(startStation, endStation).getEdgeList(); + } } diff --git a/src/main/java/subway/domain/Route.java b/src/main/java/subway/domain/Route.java index 35db3c3d1..eb7a96d07 100644 --- a/src/main/java/subway/domain/Route.java +++ b/src/main/java/subway/domain/Route.java @@ -17,4 +17,8 @@ public List findShortestRoute(final String startStation, final String en public Distance findShortestRouteDistance(final String startStation, final String endStation) { return routeFinder.findShortestRouteDistance(startStation, endStation); } + + public List findShortestRouteSections(final String startStation, final String endStation) { + return routeFinder.findShortestRouteSections(startStation, endStation); + } } diff --git a/src/main/java/subway/domain/RouteFinder.java b/src/main/java/subway/domain/RouteFinder.java index 56d3f1b52..4b205ef4b 100644 --- a/src/main/java/subway/domain/RouteFinder.java +++ b/src/main/java/subway/domain/RouteFinder.java @@ -7,4 +7,6 @@ public interface RouteFinder { List findShortestRoute(final String startStation, final String endStation); Distance findShortestRouteDistance(final String startStation, final String endStation); + + List findShortestRouteSections(final String startStation, final String endStation); } diff --git a/src/test/java/subway/domain/RouteTest.java b/src/test/java/subway/domain/RouteTest.java index ea32b4593..12b3e1dae 100644 --- a/src/test/java/subway/domain/RouteTest.java +++ b/src/test/java/subway/domain/RouteTest.java @@ -7,10 +7,12 @@ import org.junit.jupiter.params.provider.MethodSource; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -139,6 +141,48 @@ void test_findShortestRoute_IllegalArgumentException_notContainStartOrEnd() thro .isInstanceOf(IllegalArgumentException.class); } + /** + * 11 5 + * F -- G -- H + * 4 | | 4 + * | | + * A -- B -- C -- D + * 1 2 3 + */ + + @Test + @DisplayName("findShortestRouteSections() : 최단 경로에 속한 섹션들을 구할 수 있다.") + void test_findShortestRouteSections() throws Exception { + //given + final List lines = createDefaultLines(); + final Route route = new Route(lines); + + final String start = "A"; + final String end = "G"; + + //when + final List shortestRouteSections = route.findShortestRouteSections(start, end); + + //then + final List startStations = + shortestRouteSections.stream() + .map(EdgeSection::getStartStation) + .collect(Collectors.toList()); + + final List endStations = + shortestRouteSections.stream() + .map(EdgeSection::getEndStation) + .collect(Collectors.toList()); + + assertAll( + () -> assertEquals(5, shortestRouteSections.size()), + () -> assertThat(startStations).containsAnyElementsOf( + List.of("A", "B", "C", "D", "H")), + () -> assertThat(endStations).containsAnyElementsOf( + List.of("B", "C", "D", "H", "G")) + ); + } + private List createDefaultLines() { final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); From 8eb76382490df3a9e95f2bd4cd69a85ef517a640 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 00:25:50 +0900 Subject: [PATCH 05/41] =?UTF-8?q?feat=20:=20=ED=98=B8=EC=84=A0=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=EC=84=9C=20=EC=9A=94=EA=B8=88=20=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SubwayPricePolicy - 파라미터 Route 로 수정 Route - 파라미터로 조회할 경로의 출발, 도착역 추가 --- .../subway/domain/DefaultPricePolicy.java | 5 +- .../java/subway/domain/LinePricePolicy.java | 25 ++++++ .../subway/domain/PricePolicyComposite.java | 24 ++++++ src/main/java/subway/domain/Route.java | 22 ++++-- .../java/subway/domain/SubwayPricePolicy.java | 2 +- .../subway/service/RouteQueryService.java | 32 +++++--- .../subway/domain/DefaultPricePolicyTest.java | 79 ++++++++++++++++--- .../domain/PricePolicyCompositeTest.java | 75 ++++++++++++++++++ src/test/java/subway/domain/RouteTest.java | 44 +++++------ 9 files changed, 255 insertions(+), 53 deletions(-) create mode 100644 src/main/java/subway/domain/LinePricePolicy.java create mode 100644 src/main/java/subway/domain/PricePolicyComposite.java create mode 100644 src/test/java/subway/domain/PricePolicyCompositeTest.java diff --git a/src/main/java/subway/domain/DefaultPricePolicy.java b/src/main/java/subway/domain/DefaultPricePolicy.java index 76bcfa2d0..bb24eb7c8 100644 --- a/src/main/java/subway/domain/DefaultPricePolicy.java +++ b/src/main/java/subway/domain/DefaultPricePolicy.java @@ -15,10 +15,9 @@ public class DefaultPricePolicy implements SubwayPricePolicy { private static final int MID_DISTANCE_RATE = 5; private static final int LONG_DISTANCE_RATE = 8; - @Override - public int calculate(final int distance) { - final Distance distanceValue = new Distance(distance); + public int calculate(final Route route) { + final Distance distanceValue = route.findShortestRouteDistance(); if (distanceValue.isDefaultDistance()) { return DEFAULT_PRICE.intValue(); diff --git a/src/main/java/subway/domain/LinePricePolicy.java b/src/main/java/subway/domain/LinePricePolicy.java new file mode 100644 index 000000000..2fecae305 --- /dev/null +++ b/src/main/java/subway/domain/LinePricePolicy.java @@ -0,0 +1,25 @@ +package subway.domain; + +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Component +public class LinePricePolicy implements SubwayPricePolicy { + + private static final Map priceMap + = Map.of("1호선", 500, + "2호선", 1000); + + @Override + public int calculate(final Route route) { + + final List shortestRouteSections = route.findShortestRouteSections(); + + return shortestRouteSections.stream() + .mapToInt(it -> priceMap.getOrDefault(it.getLineName(), 0)) + .max() + .orElse(0); + } +} diff --git a/src/main/java/subway/domain/PricePolicyComposite.java b/src/main/java/subway/domain/PricePolicyComposite.java new file mode 100644 index 000000000..f39bdb2f2 --- /dev/null +++ b/src/main/java/subway/domain/PricePolicyComposite.java @@ -0,0 +1,24 @@ +package subway.domain; + +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Primary +@Component +public class PricePolicyComposite implements SubwayPricePolicy { + + private final List policies; + + public PricePolicyComposite(final List policies) { + this.policies = policies; + } + + @Override + public int calculate(final Route route) { + return policies.stream() + .mapToInt(it -> it.calculate(route)) + .sum(); + } +} diff --git a/src/main/java/subway/domain/Route.java b/src/main/java/subway/domain/Route.java index eb7a96d07..9afdb8ac5 100644 --- a/src/main/java/subway/domain/Route.java +++ b/src/main/java/subway/domain/Route.java @@ -5,20 +5,28 @@ public class Route { private final RouteFinder routeFinder; + private final Station from; + private final Station to; - public Route(final List lines) { + public Route( + final List lines, + final Station from, + final Station to + ) { this.routeFinder = new JgraphtRouteFinder(lines); + this.from = from; + this.to = to; } - public List findShortestRoute(final String startStation, final String endStation) { - return routeFinder.findShortestRoute(startStation, endStation); + public List findShortestRoute() { + return routeFinder.findShortestRoute(from.getName(), to.getName()); } - public Distance findShortestRouteDistance(final String startStation, final String endStation) { - return routeFinder.findShortestRouteDistance(startStation, endStation); + public Distance findShortestRouteDistance() { + return routeFinder.findShortestRouteDistance(from.getName(), to.getName()); } - public List findShortestRouteSections(final String startStation, final String endStation) { - return routeFinder.findShortestRouteSections(startStation, endStation); + public List findShortestRouteSections() { + return routeFinder.findShortestRouteSections(from.getName(), to.getName()); } } diff --git a/src/main/java/subway/domain/SubwayPricePolicy.java b/src/main/java/subway/domain/SubwayPricePolicy.java index ac5cb5cd1..cc1e495f8 100644 --- a/src/main/java/subway/domain/SubwayPricePolicy.java +++ b/src/main/java/subway/domain/SubwayPricePolicy.java @@ -2,5 +2,5 @@ public interface SubwayPricePolicy { - int calculate(final int distance); + int calculate(final Route route); } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 9d4f8430d..b5b869841 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -3,6 +3,7 @@ import org.springframework.stereotype.Service; import subway.domain.Line; import subway.domain.Route; +import subway.domain.Station; import subway.domain.SubwayPricePolicy; import subway.service.dto.ShortestRouteRequest; @@ -23,26 +24,37 @@ public List searchShortestRoute(final ShortestRouteRequest shortestRoute final List lines = lineQueryService.searchAllLine(); - final Route route = new Route(lines); - - return route.findShortestRoute( - shortestRouteRequest.getStartStation(), - shortestRouteRequest.getEndStation() + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) ); + + return route.findShortestRoute(); } public int searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { - return subwayPricePolicy.calculate(searchShortestDistance(shortestRouteRequest)); + final List lines = lineQueryService.searchAllLine(); + + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) + ); + + return subwayPricePolicy.calculate(route); } public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { final List lines = lineQueryService.searchAllLine(); - final Route route = new Route(lines); + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) + ); - return route.findShortestRouteDistance( - shortestRouteRequest.getStartStation(), - shortestRouteRequest.getEndStation()) + return route.findShortestRouteDistance() .getValue(); } diff --git a/src/test/java/subway/domain/DefaultPricePolicyTest.java b/src/test/java/subway/domain/DefaultPricePolicyTest.java index 5ab189039..9f1e47abe 100644 --- a/src/test/java/subway/domain/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/DefaultPricePolicyTest.java @@ -3,7 +3,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -17,15 +21,70 @@ void setUp() { } @ParameterizedTest - @CsvSource({ - "9,1250", - "12,1350", - "16,1450", - "58,2150" - }) + @MethodSource("calculatePriceFromDistance") @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") - void test_calculate(final int distance, final int price) throws Exception { - //when & then - assertEquals(price, subwayPricePolicy.calculate(distance)); + void test_calculate(final Station from, final Station to, final int price) throws Exception { + //given + final List lines = createDefaultLines(); + final Route route = new Route(lines, from, to); + + //when + final int result = subwayPricePolicy.calculate(route); + + //then + assertEquals(result, price); + } + + static Stream calculatePriceFromDistance() { + + final Station start1 = new Station("A"); + final Station end1 = new Station("G"); + final int price1 = 1350; + + final Station start2 = new Station("A"); + final Station end2 = new Station("H"); + final int price2 = 1250; + + final Station start3 = new Station("G"); + final Station end3 = new Station("C"); + final int price3 = 1350; + + final Station start4 = new Station("F"); + final Station end4 = new Station("H"); + final int price4 = 1350; + + return Stream.of( + Arguments.of(start1, end1, price1), + Arguments.of(start2, end2, price2), + Arguments.of(start3, end3, price3), + Arguments.of(start4, end4, price4) + ); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); } } diff --git a/src/test/java/subway/domain/PricePolicyCompositeTest.java b/src/test/java/subway/domain/PricePolicyCompositeTest.java new file mode 100644 index 000000000..a108e994d --- /dev/null +++ b/src/test/java/subway/domain/PricePolicyCompositeTest.java @@ -0,0 +1,75 @@ +package subway.domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PricePolicyCompositeTest { + + private PricePolicyComposite pricePolicyComposite; + + @BeforeEach + void setUp() { + pricePolicyComposite = new PricePolicyComposite( + List.of(new DefaultPricePolicy(), + new LinePricePolicy()) + ); + } + + /** + * 11 5 + * F -- G -- H + * 4 | | 4 + * | | + * A -- B -- C -- D + * 1 2 3 + */ + @Test + @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") + void test_calculate() throws Exception { + //given + final List lines = createDefaultLines(); + final Route route = new Route( + lines, + new Station("A"), + new Station("G") + ); + + //when + final int resultPrice = pricePolicyComposite.calculate(route); + + //then + assertEquals(2350, resultPrice); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } +} diff --git a/src/test/java/subway/domain/RouteTest.java b/src/test/java/subway/domain/RouteTest.java index 12b3e1dae..abd9c2c2d 100644 --- a/src/test/java/subway/domain/RouteTest.java +++ b/src/test/java/subway/domain/RouteTest.java @@ -37,10 +37,10 @@ void test_findShortestRoute( ) throws Exception { //given final List lines = createDefaultLines(); - final Route route = new Route(lines); + final Route route = new Route(lines, new Station(start), new Station(end)); //when - final List shortestRoute = route.findShortestRoute(start, end); + final List shortestRoute = route.findShortestRoute(); //then assertThat(shortestRoute).containsExactlyElementsOf(routes); @@ -84,17 +84,17 @@ static Stream findShortestRoute() { @MethodSource("findShortestRouteDistance") @DisplayName("findShortestRouteDistance() : 시작점과 도착점이 주어지면 최단 거리를 구할 수 있다.") void test_findShortestRoutePrice( - final String start, - final String end, + final Station start, + final Station end, final double distance ) throws Exception { //given final List lines = createDefaultLines(); - final Route route = new Route(lines); + final Route route = new Route(lines, start, end); //when - final Distance shortestRouteDistance = route.findShortestRouteDistance(start, end); + final Distance shortestRouteDistance = route.findShortestRouteDistance(); //then assertEquals(distance, shortestRouteDistance.getValue()); @@ -102,20 +102,20 @@ void test_findShortestRoutePrice( static Stream findShortestRouteDistance() { - final String start1 = "A"; - final String end1 = "G"; + final Station start1 = new Station("A"); + final Station end1 = new Station("G"); final double distance1 = 15.0; - final String start2 = "A"; - final String end2 = "H"; + final Station start2 = new Station("A"); + final Station end2 = new Station("H"); final double distance2 = 10.0; - final String start3 = "G"; - final String end3 = "C"; + final Station start3 = new Station("G"); + final Station end3 = new Station("C"); final double distance3 = 12.0; - final String start4 = "F"; - final String end4 = "H"; + final Station start4 = new Station("F"); + final Station end4 = new Station("H"); final double distance4 = 13.0; return Stream.of( @@ -131,13 +131,13 @@ static Stream findShortestRouteDistance() { void test_findShortestRoute_IllegalArgumentException_notContainStartOrEnd() throws Exception { //given final List lines = createDefaultLines(); - final Route route = new Route(lines); + final Station from = new Station("A"); + final Station notExistTo = new Station("K"); - final String startStation = "A"; - final String notExistEndStation = "K"; + final Route route = new Route(lines, from, notExistTo); //when & then - assertThatThrownBy(() -> route.findShortestRoute(startStation, notExistEndStation)) + assertThatThrownBy(route::findShortestRoute) .isInstanceOf(IllegalArgumentException.class); } @@ -155,13 +155,13 @@ void test_findShortestRoute_IllegalArgumentException_notContainStartOrEnd() thro void test_findShortestRouteSections() throws Exception { //given final List lines = createDefaultLines(); - final Route route = new Route(lines); + final Station from = new Station("A"); + final Station to = new Station("G"); - final String start = "A"; - final String end = "G"; + final Route route = new Route(lines, from, to); //when - final List shortestRouteSections = route.findShortestRouteSections(start, end); + final List shortestRouteSections = route.findShortestRouteSections(); //then final List startStations = From 8856369d4e1f6cdf8978341f664e5395a41433a7 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 00:27:33 +0900 Subject: [PATCH 06/41] =?UTF-8?q?refactor=20:=20SubwayPricePolicy=20->=20S?= =?UTF-8?q?ubwayChargePolicy=20=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...PolicyComposite.java => ChargePolicyComposite.java} | 6 +++--- ...efaultPricePolicy.java => DefaultChargePolicy.java} | 2 +- .../{LinePricePolicy.java => LineChargePolicy.java} | 2 +- ...{SubwayPricePolicy.java => SubwayChargePolicy.java} | 2 +- src/main/java/subway/service/RouteQueryService.java | 10 +++++----- .../java/subway/domain/DefaultPricePolicyTest.java | 6 +++--- .../java/subway/domain/PricePolicyCompositeTest.java | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) rename src/main/java/subway/domain/{PricePolicyComposite.java => ChargePolicyComposite.java} (67%) rename src/main/java/subway/domain/{DefaultPricePolicy.java => DefaultChargePolicy.java} (96%) rename src/main/java/subway/domain/{LinePricePolicy.java => LineChargePolicy.java} (91%) rename src/main/java/subway/domain/{SubwayPricePolicy.java => SubwayChargePolicy.java} (63%) diff --git a/src/main/java/subway/domain/PricePolicyComposite.java b/src/main/java/subway/domain/ChargePolicyComposite.java similarity index 67% rename from src/main/java/subway/domain/PricePolicyComposite.java rename to src/main/java/subway/domain/ChargePolicyComposite.java index f39bdb2f2..3baf30075 100644 --- a/src/main/java/subway/domain/PricePolicyComposite.java +++ b/src/main/java/subway/domain/ChargePolicyComposite.java @@ -7,11 +7,11 @@ @Primary @Component -public class PricePolicyComposite implements SubwayPricePolicy { +public class ChargePolicyComposite implements SubwayChargePolicy { - private final List policies; + private final List policies; - public PricePolicyComposite(final List policies) { + public ChargePolicyComposite(final List policies) { this.policies = policies; } diff --git a/src/main/java/subway/domain/DefaultPricePolicy.java b/src/main/java/subway/domain/DefaultChargePolicy.java similarity index 96% rename from src/main/java/subway/domain/DefaultPricePolicy.java rename to src/main/java/subway/domain/DefaultChargePolicy.java index bb24eb7c8..424a69fae 100644 --- a/src/main/java/subway/domain/DefaultPricePolicy.java +++ b/src/main/java/subway/domain/DefaultChargePolicy.java @@ -8,7 +8,7 @@ import static subway.domain.Distance.MID_DISTANCE; @Component -public class DefaultPricePolicy implements SubwayPricePolicy { +public class DefaultChargePolicy implements SubwayChargePolicy { private static final BigDecimal DEFAULT_PRICE = BigDecimal.valueOf(1250); private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); diff --git a/src/main/java/subway/domain/LinePricePolicy.java b/src/main/java/subway/domain/LineChargePolicy.java similarity index 91% rename from src/main/java/subway/domain/LinePricePolicy.java rename to src/main/java/subway/domain/LineChargePolicy.java index 2fecae305..56bc7ad9c 100644 --- a/src/main/java/subway/domain/LinePricePolicy.java +++ b/src/main/java/subway/domain/LineChargePolicy.java @@ -6,7 +6,7 @@ import java.util.Map; @Component -public class LinePricePolicy implements SubwayPricePolicy { +public class LineChargePolicy implements SubwayChargePolicy { private static final Map priceMap = Map.of("1호선", 500, diff --git a/src/main/java/subway/domain/SubwayPricePolicy.java b/src/main/java/subway/domain/SubwayChargePolicy.java similarity index 63% rename from src/main/java/subway/domain/SubwayPricePolicy.java rename to src/main/java/subway/domain/SubwayChargePolicy.java index cc1e495f8..4d0a86d79 100644 --- a/src/main/java/subway/domain/SubwayPricePolicy.java +++ b/src/main/java/subway/domain/SubwayChargePolicy.java @@ -1,6 +1,6 @@ package subway.domain; -public interface SubwayPricePolicy { +public interface SubwayChargePolicy { int calculate(final Route route); } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index b5b869841..dedc4d05a 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -4,7 +4,7 @@ import subway.domain.Line; import subway.domain.Route; import subway.domain.Station; -import subway.domain.SubwayPricePolicy; +import subway.domain.SubwayChargePolicy; import subway.service.dto.ShortestRouteRequest; import java.util.List; @@ -13,11 +13,11 @@ public class RouteQueryService { private final LineQueryService lineQueryService; - private final SubwayPricePolicy subwayPricePolicy; + private final SubwayChargePolicy subwayChargePolicy; - public RouteQueryService(final LineQueryService lineQueryService, final SubwayPricePolicy subwayPricePolicy) { + public RouteQueryService(final LineQueryService lineQueryService, final SubwayChargePolicy subwayChargePolicy) { this.lineQueryService = lineQueryService; - this.subwayPricePolicy = subwayPricePolicy; + this.subwayChargePolicy = subwayChargePolicy; } public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { @@ -42,7 +42,7 @@ public int searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { new Station(shortestRouteRequest.getEndStation()) ); - return subwayPricePolicy.calculate(route); + return subwayChargePolicy.calculate(route); } public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { diff --git a/src/test/java/subway/domain/DefaultPricePolicyTest.java b/src/test/java/subway/domain/DefaultPricePolicyTest.java index 9f1e47abe..05f89e4c4 100644 --- a/src/test/java/subway/domain/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/DefaultPricePolicyTest.java @@ -13,11 +13,11 @@ class DefaultPricePolicyTest { - private SubwayPricePolicy subwayPricePolicy; + private SubwayChargePolicy subwayChargePolicy; @BeforeEach void setUp() { - subwayPricePolicy = new DefaultPricePolicy(); + subwayChargePolicy = new DefaultChargePolicy(); } @ParameterizedTest @@ -29,7 +29,7 @@ void test_calculate(final Station from, final Station to, final int price) throw final Route route = new Route(lines, from, to); //when - final int result = subwayPricePolicy.calculate(route); + final int result = subwayChargePolicy.calculate(route); //then assertEquals(result, price); diff --git a/src/test/java/subway/domain/PricePolicyCompositeTest.java b/src/test/java/subway/domain/PricePolicyCompositeTest.java index a108e994d..bd56db50b 100644 --- a/src/test/java/subway/domain/PricePolicyCompositeTest.java +++ b/src/test/java/subway/domain/PricePolicyCompositeTest.java @@ -10,13 +10,13 @@ class PricePolicyCompositeTest { - private PricePolicyComposite pricePolicyComposite; + private ChargePolicyComposite pricePolicyComposite; @BeforeEach void setUp() { - pricePolicyComposite = new PricePolicyComposite( - List.of(new DefaultPricePolicy(), - new LinePricePolicy()) + pricePolicyComposite = new ChargePolicyComposite( + List.of(new DefaultChargePolicy(), + new LineChargePolicy()) ); } From e8ec92658914c42c630c0b139fc579b5987bab00 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 01:56:13 +0900 Subject: [PATCH 07/41] =?UTF-8?q?feat=20:=20=EC=97=B0=EB=A0=B9=EB=B3=84=20?= =?UTF-8?q?=EC=9A=94=EA=B8=88=20=ED=95=A0=EC=9D=B8=20=EC=A0=95=EC=B1=85=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/subway/domain/AgeDiscountPolicy.java | 47 +++++++++++++++++ src/main/java/subway/domain/AgeGroup.java | 27 ++++++++++ .../java/subway/domain/DiscountCondition.java | 14 +++++ src/main/java/subway/domain/Money.java | 52 +++++++++++++++++++ .../subway/domain/SubwayDiscountPolicy.java | 6 +++ .../subway/service/RouteQueryService.java | 19 +++++-- .../service/dto/ShortestRouteRequest.java | 12 +++-- .../service/dto/ShortestRouteResponse.java | 6 +-- src/test/java/subway/domain/MoneyTest.java | 47 +++++++++++++++++ 9 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 src/main/java/subway/domain/AgeDiscountPolicy.java create mode 100644 src/main/java/subway/domain/AgeGroup.java create mode 100644 src/main/java/subway/domain/DiscountCondition.java create mode 100644 src/main/java/subway/domain/Money.java create mode 100644 src/main/java/subway/domain/SubwayDiscountPolicy.java create mode 100644 src/test/java/subway/domain/MoneyTest.java diff --git a/src/main/java/subway/domain/AgeDiscountPolicy.java b/src/main/java/subway/domain/AgeDiscountPolicy.java new file mode 100644 index 000000000..d74ff7db9 --- /dev/null +++ b/src/main/java/subway/domain/AgeDiscountPolicy.java @@ -0,0 +1,47 @@ +package subway.domain; + +import org.springframework.stereotype.Component; + +import java.util.EnumMap; +import java.util.Map; + +@Component +public class AgeDiscountPolicy implements SubwayDiscountPolicy { + + private static final Map policyMap = new EnumMap<>(AgeGroup.class); + + static { + policyMap.put(AgeGroup.CHILD, new DiscountValue(350, 50)); + policyMap.put(AgeGroup.TEENAGER, new DiscountValue(350, 20)); + policyMap.put(AgeGroup.NONE, new DiscountValue(0, 0)); + } + + @Override + public Money discount(final DiscountCondition discountCondition, final Money price) { + + final AgeGroup ageGroup = AgeGroup.findAgeGroup(discountCondition.getAge()); + final DiscountValue discountValue = policyMap.get(ageGroup); + + return price.minus(discountValue.getDiscountPrice()) + .calculateDiscountedPrice(discountValue.getPercent()); + } + + private static class DiscountValue { + + private final int discountPrice; + private final int percent; + + public DiscountValue(final int discountPrice, final int percent) { + this.discountPrice = discountPrice; + this.percent = percent; + } + + public int getDiscountPrice() { + return discountPrice; + } + + public int getPercent() { + return percent; + } + } +} diff --git a/src/main/java/subway/domain/AgeGroup.java b/src/main/java/subway/domain/AgeGroup.java new file mode 100644 index 000000000..3186be292 --- /dev/null +++ b/src/main/java/subway/domain/AgeGroup.java @@ -0,0 +1,27 @@ +package subway.domain; + +import java.util.Arrays; +import java.util.Objects; + +public enum AgeGroup { + + TEENAGER(13, 19), + CHILD(6, 13), + NONE(0, 0); + + private final int ageLowLimit; + private final int ageHighLimit; + + AgeGroup(final int ageLowLimit, final int ageHighLimit) { + this.ageLowLimit = ageLowLimit; + this.ageHighLimit = ageHighLimit; + } + + public static AgeGroup findAgeGroup(final Integer target) { + return Arrays.stream(values()) + .filter(age -> Objects.nonNull(target)) + .filter(age -> target >= age.ageLowLimit && target < age.ageHighLimit) + .findAny() + .orElse(NONE); + } +} diff --git a/src/main/java/subway/domain/DiscountCondition.java b/src/main/java/subway/domain/DiscountCondition.java new file mode 100644 index 000000000..e7b4de708 --- /dev/null +++ b/src/main/java/subway/domain/DiscountCondition.java @@ -0,0 +1,14 @@ +package subway.domain; + +public class DiscountCondition { + + private final Integer age; + + public DiscountCondition(final Integer age) { + this.age = age; + } + + public Integer getAge() { + return age; + } +} diff --git a/src/main/java/subway/domain/Money.java b/src/main/java/subway/domain/Money.java new file mode 100644 index 000000000..d92ce95bc --- /dev/null +++ b/src/main/java/subway/domain/Money.java @@ -0,0 +1,52 @@ +package subway.domain; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Objects; + +public class Money { + + private final BigDecimal value; + + private Money(final BigDecimal value) { + validateNegative(value); + this.value = value; + } + + public Money(final double value) { + this(BigDecimal.valueOf(value)); + } + + private void validateNegative(final BigDecimal value) { + if (value.doubleValue() < 0) { + throw new IllegalArgumentException("돈은 음수가 될 수 없습니다."); + } + } + + public Money minus(final int value) { + return new Money(this.value.subtract(BigDecimal.valueOf(value))); + } + + public Money calculateDiscountedPrice(final int percentage) { + final int discountedPercentage = 100 - percentage; + return new Money(this.value.multiply(BigDecimal.valueOf(discountedPercentage)) + .divide(BigDecimal.valueOf(100), RoundingMode.HALF_DOWN)); + } + + public double getValue() { + return value.doubleValue(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final Money money = (Money) o; + return Objects.equals(value, money.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/subway/domain/SubwayDiscountPolicy.java b/src/main/java/subway/domain/SubwayDiscountPolicy.java new file mode 100644 index 000000000..44af2e2a4 --- /dev/null +++ b/src/main/java/subway/domain/SubwayDiscountPolicy.java @@ -0,0 +1,6 @@ +package subway.domain; + +public interface SubwayDiscountPolicy { + + Money discount(final DiscountCondition discountCondition, final Money price); +} diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index dedc4d05a..8b022a342 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,10 +1,13 @@ package subway.service; import org.springframework.stereotype.Service; +import subway.domain.DiscountCondition; import subway.domain.Line; +import subway.domain.Money; import subway.domain.Route; import subway.domain.Station; import subway.domain.SubwayChargePolicy; +import subway.domain.SubwayDiscountPolicy; import subway.service.dto.ShortestRouteRequest; import java.util.List; @@ -14,10 +17,16 @@ public class RouteQueryService { private final LineQueryService lineQueryService; private final SubwayChargePolicy subwayChargePolicy; + private final SubwayDiscountPolicy subwayDiscountPolicy; - public RouteQueryService(final LineQueryService lineQueryService, final SubwayChargePolicy subwayChargePolicy) { + public RouteQueryService( + final LineQueryService lineQueryService, + final SubwayChargePolicy subwayChargePolicy, + final SubwayDiscountPolicy subwayDiscountPolicy + ) { this.lineQueryService = lineQueryService; this.subwayChargePolicy = subwayChargePolicy; + this.subwayDiscountPolicy = subwayDiscountPolicy; } public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { @@ -33,7 +42,7 @@ public List searchShortestRoute(final ShortestRouteRequest shortestRoute return route.findShortestRoute(); } - public int searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { + public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { final List lines = lineQueryService.searchAllLine(); final Route route = new Route( @@ -42,7 +51,11 @@ public int searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { new Station(shortestRouteRequest.getEndStation()) ); - return subwayChargePolicy.calculate(route); + //TODO : charge 도 Money 로 변경 + final int totalPrice = subwayChargePolicy.calculate(route); + + return subwayDiscountPolicy.discount(new DiscountCondition(shortestRouteRequest.getAge()), + new Money(totalPrice)).getValue(); } public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { diff --git a/src/main/java/subway/service/dto/ShortestRouteRequest.java b/src/main/java/subway/service/dto/ShortestRouteRequest.java index ff6407935..339bfe2b0 100644 --- a/src/main/java/subway/service/dto/ShortestRouteRequest.java +++ b/src/main/java/subway/service/dto/ShortestRouteRequest.java @@ -2,12 +2,14 @@ public class ShortestRouteRequest { - private String startStation; - private String endStation; + private final String startStation; + private final String endStation; + private final Integer age; - public ShortestRouteRequest(final String startStation, final String endStation) { + public ShortestRouteRequest(final String startStation, final String endStation, final Integer age) { this.startStation = startStation; this.endStation = endStation; + this.age = age; } public String getStartStation() { @@ -17,4 +19,8 @@ public String getStartStation() { public String getEndStation() { return endStation; } + + public Integer getAge() { + return age; + } } diff --git a/src/main/java/subway/service/dto/ShortestRouteResponse.java b/src/main/java/subway/service/dto/ShortestRouteResponse.java index 7dcadaa6c..d156c6e29 100644 --- a/src/main/java/subway/service/dto/ShortestRouteResponse.java +++ b/src/main/java/subway/service/dto/ShortestRouteResponse.java @@ -5,10 +5,10 @@ public class ShortestRouteResponse { private final List stations; - private final int cost; + private final double cost; private final int distance; - public ShortestRouteResponse(final List stations, final int cost, final int distance) { + public ShortestRouteResponse(final List stations, final double cost, final int distance) { this.stations = stations; this.cost = cost; this.distance = distance; @@ -18,7 +18,7 @@ public List getStations() { return stations; } - public int getCost() { + public double getCost() { return cost; } diff --git a/src/test/java/subway/domain/MoneyTest.java b/src/test/java/subway/domain/MoneyTest.java new file mode 100644 index 000000000..37be7beb7 --- /dev/null +++ b/src/test/java/subway/domain/MoneyTest.java @@ -0,0 +1,47 @@ +package subway.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MoneyTest { + + @ParameterizedTest + @CsvSource({ + "10000, 35, 6500", + "1000, 10, 900", + "3500, 10, 3150" + }) + @DisplayName("discountPercent() : 할인을 받고 난 금액을 계산할 수 있다.") + void test_discountPercent(final int origin, final int percent, final int result) throws Exception { + //given + final Money originMoney = new Money(origin); + final Money resultMoney = new Money(result); + + //when & then + assertEquals(resultMoney, originMoney.calculateDiscountedPrice(percent)); + } + + @Test + @DisplayName("constructor() : 돈이 음수가 되면 IllegalArgumentException가 발생합니다.") + void test_constructor_IllegalArgumentException() throws Exception { + //when & then + assertThatThrownBy(() -> new Money(-1)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("discountPercent() : 할인율이 0퍼센트이면 그대로 값을 반환합니다.") + void test_discountPercent_zeroPercent() throws Exception { + //given + final Money money = new Money(10000); + final int percentage = 0; + + //when & then + assertEquals(money, money.calculateDiscountedPrice(percentage)); + } +} From dac9a3b4b804497529d999b2d6eb6372e6ad63dc Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 02:17:15 +0900 Subject: [PATCH 08/41] =?UTF-8?q?refactor=20:=20=EB=8F=88=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=AA=A8=EB=91=90=20?= =?UTF-8?q?Money=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/domain/ChargePolicyComposite.java | 6 +++--- .../subway/domain/DefaultChargePolicy.java | 11 +++++----- .../java/subway/domain/LineChargePolicy.java | 8 ++++---- src/main/java/subway/domain/Money.java | 14 +++++++++++++ .../subway/domain/SubwayChargePolicy.java | 2 +- .../subway/service/RouteQueryService.java | 7 +++---- .../subway/domain/DefaultPricePolicyTest.java | 20 +++++++++---------- .../domain/PricePolicyCompositeTest.java | 4 ++-- 8 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/main/java/subway/domain/ChargePolicyComposite.java b/src/main/java/subway/domain/ChargePolicyComposite.java index 3baf30075..d79aaa0b2 100644 --- a/src/main/java/subway/domain/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/ChargePolicyComposite.java @@ -16,9 +16,9 @@ public ChargePolicyComposite(final List policies) { } @Override - public int calculate(final Route route) { + public Money calculate(final Route route) { return policies.stream() - .mapToInt(it -> it.calculate(route)) - .sum(); + .map(it -> it.calculate(route)) + .reduce(Money.ZERO, (Money::add)); } } diff --git a/src/main/java/subway/domain/DefaultChargePolicy.java b/src/main/java/subway/domain/DefaultChargePolicy.java index 424a69fae..aa4695638 100644 --- a/src/main/java/subway/domain/DefaultChargePolicy.java +++ b/src/main/java/subway/domain/DefaultChargePolicy.java @@ -10,27 +10,26 @@ @Component public class DefaultChargePolicy implements SubwayChargePolicy { - private static final BigDecimal DEFAULT_PRICE = BigDecimal.valueOf(1250); + private static final Money DEFAULT_PRICE = new Money(1250); private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); private static final int MID_DISTANCE_RATE = 5; private static final int LONG_DISTANCE_RATE = 8; @Override - public int calculate(final Route route) { + public Money calculate(final Route route) { final Distance distanceValue = route.findShortestRouteDistance(); if (distanceValue.isDefaultDistance()) { - return DEFAULT_PRICE.intValue(); + return DEFAULT_PRICE; } if (distanceValue.isLongDistance()) { return DEFAULT_PRICE.add(calculateMidDistance(MID_DISTANCE)) .add(calculateLongDistance(distanceValue.minus(MID_DISTANCE) - .minus(DEFAULT_DISTANCE))) - .intValue(); + .minus(DEFAULT_DISTANCE))); } - return DEFAULT_PRICE.add(calculateMidDistance(distanceValue.minus(DEFAULT_DISTANCE))).intValue(); + return DEFAULT_PRICE.add(calculateMidDistance(distanceValue.minus(DEFAULT_DISTANCE))); } private BigDecimal calculateMidDistance(final Distance distance) { diff --git a/src/main/java/subway/domain/LineChargePolicy.java b/src/main/java/subway/domain/LineChargePolicy.java index 56bc7ad9c..8922cf8f7 100644 --- a/src/main/java/subway/domain/LineChargePolicy.java +++ b/src/main/java/subway/domain/LineChargePolicy.java @@ -13,13 +13,13 @@ public class LineChargePolicy implements SubwayChargePolicy { "2호선", 1000); @Override - public int calculate(final Route route) { + public Money calculate(final Route route) { final List shortestRouteSections = route.findShortestRouteSections(); return shortestRouteSections.stream() - .mapToInt(it -> priceMap.getOrDefault(it.getLineName(), 0)) - .max() - .orElse(0); + .reduce(Money.ZERO, (money, edgeSection) -> new Money( + priceMap.getOrDefault(edgeSection.getLineName(), 0)), + (Money::max)); } } diff --git a/src/main/java/subway/domain/Money.java b/src/main/java/subway/domain/Money.java index d92ce95bc..70cd6d99e 100644 --- a/src/main/java/subway/domain/Money.java +++ b/src/main/java/subway/domain/Money.java @@ -6,6 +6,8 @@ public class Money { + public static final Money ZERO = new Money(BigDecimal.ZERO); + private final BigDecimal value; private Money(final BigDecimal value) { @@ -33,6 +35,18 @@ public Money calculateDiscountedPrice(final int percentage) { .divide(BigDecimal.valueOf(100), RoundingMode.HALF_DOWN)); } + public Money add(final BigDecimal value) { + return new Money(this.value.add(value)); + } + + public Money add(final Money money) { + return new Money(this.value.add(money.value)); + } + + public Money max(final Money other) { + return new Money(this.value.max(other.value)); + } + public double getValue() { return value.doubleValue(); } diff --git a/src/main/java/subway/domain/SubwayChargePolicy.java b/src/main/java/subway/domain/SubwayChargePolicy.java index 4d0a86d79..d9ee03a5e 100644 --- a/src/main/java/subway/domain/SubwayChargePolicy.java +++ b/src/main/java/subway/domain/SubwayChargePolicy.java @@ -2,5 +2,5 @@ public interface SubwayChargePolicy { - int calculate(final Route route); + Money calculate(final Route route); } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 8b022a342..88aea9257 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -51,11 +51,10 @@ public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { new Station(shortestRouteRequest.getEndStation()) ); - //TODO : charge 도 Money 로 변경 - final int totalPrice = subwayChargePolicy.calculate(route); + final Money totalPrice = subwayChargePolicy.calculate(route); - return subwayDiscountPolicy.discount(new DiscountCondition(shortestRouteRequest.getAge()), - new Money(totalPrice)).getValue(); + return subwayDiscountPolicy.discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) + .getValue(); } public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { diff --git a/src/test/java/subway/domain/DefaultPricePolicyTest.java b/src/test/java/subway/domain/DefaultPricePolicyTest.java index 05f89e4c4..d28080652 100644 --- a/src/test/java/subway/domain/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/DefaultPricePolicyTest.java @@ -23,13 +23,13 @@ void setUp() { @ParameterizedTest @MethodSource("calculatePriceFromDistance") @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") - void test_calculate(final Station from, final Station to, final int price) throws Exception { + void test_calculate(final Station from, final Station to, final Money price) throws Exception { //given final List lines = createDefaultLines(); final Route route = new Route(lines, from, to); //when - final int result = subwayChargePolicy.calculate(route); + final Money result = subwayChargePolicy.calculate(route); //then assertEquals(result, price); @@ -39,25 +39,25 @@ static Stream calculatePriceFromDistance() { final Station start1 = new Station("A"); final Station end1 = new Station("G"); - final int price1 = 1350; + final Money money1 = new Money(1350); final Station start2 = new Station("A"); final Station end2 = new Station("H"); - final int price2 = 1250; + final Money money2 = new Money(1250); final Station start3 = new Station("G"); final Station end3 = new Station("C"); - final int price3 = 1350; + final Money money3 = new Money(1350); final Station start4 = new Station("F"); final Station end4 = new Station("H"); - final int price4 = 1350; + final Money money4 = new Money(1350); return Stream.of( - Arguments.of(start1, end1, price1), - Arguments.of(start2, end2, price2), - Arguments.of(start3, end3, price3), - Arguments.of(start4, end4, price4) + Arguments.of(start1, end1, money1), + Arguments.of(start2, end2, money2), + Arguments.of(start3, end3, money3), + Arguments.of(start4, end4, money4) ); } diff --git a/src/test/java/subway/domain/PricePolicyCompositeTest.java b/src/test/java/subway/domain/PricePolicyCompositeTest.java index bd56db50b..3dbd5020a 100644 --- a/src/test/java/subway/domain/PricePolicyCompositeTest.java +++ b/src/test/java/subway/domain/PricePolicyCompositeTest.java @@ -40,10 +40,10 @@ void test_calculate() throws Exception { ); //when - final int resultPrice = pricePolicyComposite.calculate(route); + final Money totalMoney = pricePolicyComposite.calculate(route); //then - assertEquals(2350, resultPrice); + assertEquals(new Money(2350), totalMoney); } private List createDefaultLines() { From 402a425b655558e044ecaacba913291403dfa95a Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 17:03:57 +0900 Subject: [PATCH 09/41] =?UTF-8?q?refactor=20:=20=EC=9A=94=EA=B8=88=20?= =?UTF-8?q?=ED=95=A0=EC=9D=B8,=20=EC=9A=94=EA=B8=88=20=EB=B6=80=EA=B3=BC?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=EC=9D=84=20ChargePolicyComposite=20?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=AA=A8=EB=91=90=20=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/domain/ChargePolicyComposite.java | 27 ++++++++++++++----- ...argePolicy.java => DefaultFarePolicy.java} | 2 +- ...eChargePolicy.java => LineFarePolicy.java} | 6 ++--- ...hargePolicy.java => SubwayFarePolicy.java} | 2 +- .../subway/service/RouteQueryService.java | 18 +++++-------- ...st.java => ChargePolicyCompositeTest.java} | 21 ++++++++++++--- .../subway/domain/DefaultPricePolicyTest.java | 6 ++--- 7 files changed, 53 insertions(+), 29 deletions(-) rename src/main/java/subway/domain/{DefaultChargePolicy.java => DefaultFarePolicy.java} (96%) rename src/main/java/subway/domain/{LineChargePolicy.java => LineFarePolicy.java} (75%) rename src/main/java/subway/domain/{SubwayChargePolicy.java => SubwayFarePolicy.java} (63%) rename src/test/java/subway/domain/{PricePolicyCompositeTest.java => ChargePolicyCompositeTest.java} (78%) diff --git a/src/main/java/subway/domain/ChargePolicyComposite.java b/src/main/java/subway/domain/ChargePolicyComposite.java index d79aaa0b2..756cd8538 100644 --- a/src/main/java/subway/domain/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/ChargePolicyComposite.java @@ -7,18 +7,31 @@ @Primary @Component -public class ChargePolicyComposite implements SubwayChargePolicy { +public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { - private final List policies; + private final List farePolicies; + private final List discountPolicies; - public ChargePolicyComposite(final List policies) { - this.policies = policies; + public ChargePolicyComposite( + final List farePolicies, + final List discountPolicies + ) { + this.farePolicies = farePolicies; + this.discountPolicies = discountPolicies; } @Override public Money calculate(final Route route) { - return policies.stream() - .map(it -> it.calculate(route)) - .reduce(Money.ZERO, (Money::add)); + return farePolicies.stream() + .map(it -> it.calculate(route)) + .reduce(Money.ZERO, Money::add); + } + + @Override + public Money discount(final DiscountCondition discountCondition, final Money price) { + return discountPolicies.stream() + .reduce(price, (money, subwayDiscountPolicy) -> + subwayDiscountPolicy.discount(discountCondition, money), + (money1, money2) -> money2); } } diff --git a/src/main/java/subway/domain/DefaultChargePolicy.java b/src/main/java/subway/domain/DefaultFarePolicy.java similarity index 96% rename from src/main/java/subway/domain/DefaultChargePolicy.java rename to src/main/java/subway/domain/DefaultFarePolicy.java index aa4695638..68aaf88e6 100644 --- a/src/main/java/subway/domain/DefaultChargePolicy.java +++ b/src/main/java/subway/domain/DefaultFarePolicy.java @@ -8,7 +8,7 @@ import static subway.domain.Distance.MID_DISTANCE; @Component -public class DefaultChargePolicy implements SubwayChargePolicy { +public class DefaultFarePolicy implements SubwayFarePolicy { private static final Money DEFAULT_PRICE = new Money(1250); private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); diff --git a/src/main/java/subway/domain/LineChargePolicy.java b/src/main/java/subway/domain/LineFarePolicy.java similarity index 75% rename from src/main/java/subway/domain/LineChargePolicy.java rename to src/main/java/subway/domain/LineFarePolicy.java index 8922cf8f7..51a916e09 100644 --- a/src/main/java/subway/domain/LineChargePolicy.java +++ b/src/main/java/subway/domain/LineFarePolicy.java @@ -6,7 +6,7 @@ import java.util.Map; @Component -public class LineChargePolicy implements SubwayChargePolicy { +public class LineFarePolicy implements SubwayFarePolicy { private static final Map priceMap = Map.of("1호선", 500, @@ -18,8 +18,8 @@ public Money calculate(final Route route) { final List shortestRouteSections = route.findShortestRouteSections(); return shortestRouteSections.stream() - .reduce(Money.ZERO, (money, edgeSection) -> new Money( - priceMap.getOrDefault(edgeSection.getLineName(), 0)), + .reduce(Money.ZERO, (money, edgeSection) -> + new Money(priceMap.getOrDefault(edgeSection.getLineName(), 0)), (Money::max)); } } diff --git a/src/main/java/subway/domain/SubwayChargePolicy.java b/src/main/java/subway/domain/SubwayFarePolicy.java similarity index 63% rename from src/main/java/subway/domain/SubwayChargePolicy.java rename to src/main/java/subway/domain/SubwayFarePolicy.java index d9ee03a5e..d61df6d68 100644 --- a/src/main/java/subway/domain/SubwayChargePolicy.java +++ b/src/main/java/subway/domain/SubwayFarePolicy.java @@ -1,6 +1,6 @@ package subway.domain; -public interface SubwayChargePolicy { +public interface SubwayFarePolicy { Money calculate(final Route route); } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 88aea9257..f8fad58ce 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,13 +1,12 @@ package subway.service; import org.springframework.stereotype.Service; +import subway.domain.ChargePolicyComposite; import subway.domain.DiscountCondition; import subway.domain.Line; import subway.domain.Money; import subway.domain.Route; import subway.domain.Station; -import subway.domain.SubwayChargePolicy; -import subway.domain.SubwayDiscountPolicy; import subway.service.dto.ShortestRouteRequest; import java.util.List; @@ -16,17 +15,14 @@ public class RouteQueryService { private final LineQueryService lineQueryService; - private final SubwayChargePolicy subwayChargePolicy; - private final SubwayDiscountPolicy subwayDiscountPolicy; + private final ChargePolicyComposite chargePolicyComposite; public RouteQueryService( final LineQueryService lineQueryService, - final SubwayChargePolicy subwayChargePolicy, - final SubwayDiscountPolicy subwayDiscountPolicy + final ChargePolicyComposite chargePolicyComposite ) { this.lineQueryService = lineQueryService; - this.subwayChargePolicy = subwayChargePolicy; - this.subwayDiscountPolicy = subwayDiscountPolicy; + this.chargePolicyComposite = chargePolicyComposite; } public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { @@ -51,10 +47,10 @@ public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { new Station(shortestRouteRequest.getEndStation()) ); - final Money totalPrice = subwayChargePolicy.calculate(route); + final Money totalPrice = chargePolicyComposite.calculate(route); - return subwayDiscountPolicy.discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) - .getValue(); + return chargePolicyComposite.discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) + .getValue(); } public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { diff --git a/src/test/java/subway/domain/PricePolicyCompositeTest.java b/src/test/java/subway/domain/ChargePolicyCompositeTest.java similarity index 78% rename from src/test/java/subway/domain/PricePolicyCompositeTest.java rename to src/test/java/subway/domain/ChargePolicyCompositeTest.java index 3dbd5020a..a9b97d230 100644 --- a/src/test/java/subway/domain/PricePolicyCompositeTest.java +++ b/src/test/java/subway/domain/ChargePolicyCompositeTest.java @@ -8,15 +8,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class PricePolicyCompositeTest { +class ChargePolicyCompositeTest { private ChargePolicyComposite pricePolicyComposite; @BeforeEach void setUp() { pricePolicyComposite = new ChargePolicyComposite( - List.of(new DefaultChargePolicy(), - new LineChargePolicy()) + List.of(new DefaultFarePolicy(), + new LineFarePolicy()), + List.of(new AgeDiscountPolicy()) ); } @@ -46,6 +47,20 @@ void test_calculate() throws Exception { assertEquals(new Money(2350), totalMoney); } + @Test + @DisplayName("discount() : 모든 할인 요금 정책을 계산할 수 있다.") + void test_discount() throws Exception { + //given + final DiscountCondition discountCondition = new DiscountCondition(14); + final Money money = new Money(10350); + + //when + final Money discountedMoney = pricePolicyComposite.discount(discountCondition, money); + + //then + assertEquals(new Money(8000), discountedMoney); + } + private List createDefaultLines() { final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); diff --git a/src/test/java/subway/domain/DefaultPricePolicyTest.java b/src/test/java/subway/domain/DefaultPricePolicyTest.java index d28080652..72a80f240 100644 --- a/src/test/java/subway/domain/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/DefaultPricePolicyTest.java @@ -13,11 +13,11 @@ class DefaultPricePolicyTest { - private SubwayChargePolicy subwayChargePolicy; + private SubwayFarePolicy subwayFarePolicy; @BeforeEach void setUp() { - subwayChargePolicy = new DefaultChargePolicy(); + subwayFarePolicy = new DefaultFarePolicy(); } @ParameterizedTest @@ -29,7 +29,7 @@ void test_calculate(final Station from, final Station to, final Money price) thr final Route route = new Route(lines, from, to); //when - final Money result = subwayChargePolicy.calculate(route); + final Money result = subwayFarePolicy.calculate(route); //then assertEquals(result, price); From c2f7753abcef3b592af689c110a0565878acd1f0 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 17:14:15 +0900 Subject: [PATCH 10/41] =?UTF-8?q?refactor=20:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/controller/LineController.java | 2 +- src/main/java/subway/domain/SubwayFarePolicy.java | 6 ------ src/main/java/subway/domain/{ => line}/Line.java | 5 ++++- .../domain/{ => policy}/ChargePolicyComposite.java | 7 ++++++- .../{ => policy/discount}/AgeDiscountPolicy.java | 3 ++- .../domain/{ => policy/discount}/AgeGroup.java | 2 +- .../{ => policy/discount}/DiscountCondition.java | 2 +- .../{ => policy/discount}/SubwayDiscountPolicy.java | 4 +++- .../domain/{ => policy/fare}/DefaultFarePolicy.java | 5 ++++- .../domain/{ => policy/fare}/LineFarePolicy.java | 5 ++++- .../subway/domain/policy/fare/SubwayFarePolicy.java | 9 +++++++++ .../java/subway/domain/{ => route}/EdgeSection.java | 2 +- .../domain/{ => route}/JgraphtRouteFinder.java | 6 +++++- src/main/java/subway/domain/{ => route}/Route.java | 6 +++++- .../java/subway/domain/{ => route}/RouteFinder.java | 4 +++- .../java/subway/domain/{ => section}/Section.java | 5 ++++- .../java/subway/domain/{ => station}/Station.java | 2 +- .../java/subway/domain/{ => station}/Stations.java | 4 +++- src/main/java/subway/service/LineQueryService.java | 2 +- src/main/java/subway/service/RouteQueryService.java | 10 +++++----- .../java/subway/service/SectionCommandService.java | 6 +++--- .../java/subway/service/SectionQueryService.java | 6 +++--- src/main/java/subway/service/StationService.java | 8 ++++---- src/test/java/subway/domain/LineTest.java | 4 ++++ src/test/java/subway/domain/RouteTest.java | 6 ++++++ src/test/java/subway/domain/SectionTest.java | 3 +++ src/test/java/subway/domain/StationTest.java | 1 + src/test/java/subway/domain/StationsTest.java | 2 ++ .../{ => policy}/ChargePolicyCompositeTest.java | 12 +++++++++++- .../{ => policy/fare}/DefaultPricePolicyTest.java | 8 +++++++- 30 files changed, 107 insertions(+), 40 deletions(-) delete mode 100644 src/main/java/subway/domain/SubwayFarePolicy.java rename src/main/java/subway/domain/{ => line}/Line.java (97%) rename src/main/java/subway/domain/{ => policy}/ChargePolicyComposite.java (82%) rename src/main/java/subway/domain/{ => policy/discount}/AgeDiscountPolicy.java (95%) rename src/main/java/subway/domain/{ => policy/discount}/AgeGroup.java (94%) rename src/main/java/subway/domain/{ => policy/discount}/DiscountCondition.java (84%) rename src/main/java/subway/domain/{ => policy/discount}/SubwayDiscountPolicy.java (64%) rename src/main/java/subway/domain/{ => policy/fare}/DefaultFarePolicy.java (92%) rename src/main/java/subway/domain/{ => policy/fare}/LineFarePolicy.java (84%) create mode 100644 src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java rename src/main/java/subway/domain/{ => route}/EdgeSection.java (96%) rename src/main/java/subway/domain/{ => route}/JgraphtRouteFinder.java (94%) rename src/main/java/subway/domain/{ => route}/Route.java (86%) rename src/main/java/subway/domain/{ => route}/RouteFinder.java (84%) rename src/main/java/subway/domain/{ => section}/Section.java (97%) rename src/main/java/subway/domain/{ => station}/Station.java (93%) rename src/main/java/subway/domain/{ => station}/Stations.java (96%) rename src/test/java/subway/domain/{ => policy}/ChargePolicyCompositeTest.java (86%) rename src/test/java/subway/domain/{ => policy/fare}/DefaultPricePolicyTest.java (93%) diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index 57dc1f25f..30f835c6d 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import subway.domain.Line; +import subway.domain.line.Line; import subway.service.LineCommandService; import subway.service.LineQueryService; import subway.service.dto.LineResponse; diff --git a/src/main/java/subway/domain/SubwayFarePolicy.java b/src/main/java/subway/domain/SubwayFarePolicy.java deleted file mode 100644 index d61df6d68..000000000 --- a/src/main/java/subway/domain/SubwayFarePolicy.java +++ /dev/null @@ -1,6 +0,0 @@ -package subway.domain; - -public interface SubwayFarePolicy { - - Money calculate(final Route route); -} diff --git a/src/main/java/subway/domain/Line.java b/src/main/java/subway/domain/line/Line.java similarity index 97% rename from src/main/java/subway/domain/Line.java rename to src/main/java/subway/domain/line/Line.java index b77b59375..5ec89b657 100644 --- a/src/main/java/subway/domain/Line.java +++ b/src/main/java/subway/domain/line/Line.java @@ -1,4 +1,7 @@ -package subway.domain; +package subway.domain.line; + +import subway.domain.section.Section; +import subway.domain.station.Station; import java.util.ArrayList; import java.util.Collection; diff --git a/src/main/java/subway/domain/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java similarity index 82% rename from src/main/java/subway/domain/ChargePolicyComposite.java rename to src/main/java/subway/domain/policy/ChargePolicyComposite.java index 756cd8538..517f58edb 100644 --- a/src/main/java/subway/domain/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -1,7 +1,12 @@ -package subway.domain; +package subway.domain.policy; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; +import subway.domain.Money; +import subway.domain.policy.discount.DiscountCondition; +import subway.domain.policy.discount.SubwayDiscountPolicy; +import subway.domain.policy.fare.SubwayFarePolicy; +import subway.domain.route.Route; import java.util.List; diff --git a/src/main/java/subway/domain/AgeDiscountPolicy.java b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java similarity index 95% rename from src/main/java/subway/domain/AgeDiscountPolicy.java rename to src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java index d74ff7db9..c6e0ce4ed 100644 --- a/src/main/java/subway/domain/AgeDiscountPolicy.java +++ b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java @@ -1,6 +1,7 @@ -package subway.domain; +package subway.domain.policy.discount; import org.springframework.stereotype.Component; +import subway.domain.Money; import java.util.EnumMap; import java.util.Map; diff --git a/src/main/java/subway/domain/AgeGroup.java b/src/main/java/subway/domain/policy/discount/AgeGroup.java similarity index 94% rename from src/main/java/subway/domain/AgeGroup.java rename to src/main/java/subway/domain/policy/discount/AgeGroup.java index 3186be292..db10ccd66 100644 --- a/src/main/java/subway/domain/AgeGroup.java +++ b/src/main/java/subway/domain/policy/discount/AgeGroup.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.domain.policy.discount; import java.util.Arrays; import java.util.Objects; diff --git a/src/main/java/subway/domain/DiscountCondition.java b/src/main/java/subway/domain/policy/discount/DiscountCondition.java similarity index 84% rename from src/main/java/subway/domain/DiscountCondition.java rename to src/main/java/subway/domain/policy/discount/DiscountCondition.java index e7b4de708..b126ac336 100644 --- a/src/main/java/subway/domain/DiscountCondition.java +++ b/src/main/java/subway/domain/policy/discount/DiscountCondition.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.domain.policy.discount; public class DiscountCondition { diff --git a/src/main/java/subway/domain/SubwayDiscountPolicy.java b/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java similarity index 64% rename from src/main/java/subway/domain/SubwayDiscountPolicy.java rename to src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java index 44af2e2a4..9df7bea2d 100644 --- a/src/main/java/subway/domain/SubwayDiscountPolicy.java +++ b/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java @@ -1,4 +1,6 @@ -package subway.domain; +package subway.domain.policy.discount; + +import subway.domain.Money; public interface SubwayDiscountPolicy { diff --git a/src/main/java/subway/domain/DefaultFarePolicy.java b/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java similarity index 92% rename from src/main/java/subway/domain/DefaultFarePolicy.java rename to src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java index 68aaf88e6..38da25fef 100644 --- a/src/main/java/subway/domain/DefaultFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java @@ -1,6 +1,9 @@ -package subway.domain; +package subway.domain.policy.fare; import org.springframework.stereotype.Component; +import subway.domain.Distance; +import subway.domain.Money; +import subway.domain.route.Route; import java.math.BigDecimal; diff --git a/src/main/java/subway/domain/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java similarity index 84% rename from src/main/java/subway/domain/LineFarePolicy.java rename to src/main/java/subway/domain/policy/fare/LineFarePolicy.java index 51a916e09..ef2719813 100644 --- a/src/main/java/subway/domain/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -1,6 +1,9 @@ -package subway.domain; +package subway.domain.policy.fare; import org.springframework.stereotype.Component; +import subway.domain.Money; +import subway.domain.route.EdgeSection; +import subway.domain.route.Route; import java.util.List; import java.util.Map; diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java new file mode 100644 index 000000000..36e4a080a --- /dev/null +++ b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java @@ -0,0 +1,9 @@ +package subway.domain.policy.fare; + +import subway.domain.Money; +import subway.domain.route.Route; + +public interface SubwayFarePolicy { + + Money calculate(final Route route); +} diff --git a/src/main/java/subway/domain/EdgeSection.java b/src/main/java/subway/domain/route/EdgeSection.java similarity index 96% rename from src/main/java/subway/domain/EdgeSection.java rename to src/main/java/subway/domain/route/EdgeSection.java index f6a87c288..70204758b 100644 --- a/src/main/java/subway/domain/EdgeSection.java +++ b/src/main/java/subway/domain/route/EdgeSection.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.domain.route; import org.jgrapht.graph.DefaultWeightedEdge; diff --git a/src/main/java/subway/domain/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java similarity index 94% rename from src/main/java/subway/domain/JgraphtRouteFinder.java rename to src/main/java/subway/domain/route/JgraphtRouteFinder.java index f8da087c1..d0cd8f926 100644 --- a/src/main/java/subway/domain/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -1,8 +1,12 @@ -package subway.domain; +package subway.domain.route; import org.jgrapht.Graph; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.WeightedMultigraph; +import subway.domain.Distance; +import subway.domain.line.Line; +import subway.domain.section.Section; +import subway.domain.station.Stations; import java.util.List; diff --git a/src/main/java/subway/domain/Route.java b/src/main/java/subway/domain/route/Route.java similarity index 86% rename from src/main/java/subway/domain/Route.java rename to src/main/java/subway/domain/route/Route.java index 9afdb8ac5..8ec27d44a 100644 --- a/src/main/java/subway/domain/Route.java +++ b/src/main/java/subway/domain/route/Route.java @@ -1,4 +1,8 @@ -package subway.domain; +package subway.domain.route; + +import subway.domain.Distance; +import subway.domain.line.Line; +import subway.domain.station.Station; import java.util.List; diff --git a/src/main/java/subway/domain/RouteFinder.java b/src/main/java/subway/domain/route/RouteFinder.java similarity index 84% rename from src/main/java/subway/domain/RouteFinder.java rename to src/main/java/subway/domain/route/RouteFinder.java index 4b205ef4b..21df2961c 100644 --- a/src/main/java/subway/domain/RouteFinder.java +++ b/src/main/java/subway/domain/route/RouteFinder.java @@ -1,4 +1,6 @@ -package subway.domain; +package subway.domain.route; + +import subway.domain.Distance; import java.util.List; diff --git a/src/main/java/subway/domain/Section.java b/src/main/java/subway/domain/section/Section.java similarity index 97% rename from src/main/java/subway/domain/Section.java rename to src/main/java/subway/domain/section/Section.java index 01203fc91..908e48658 100644 --- a/src/main/java/subway/domain/Section.java +++ b/src/main/java/subway/domain/section/Section.java @@ -1,4 +1,7 @@ -package subway.domain; +package subway.domain.section; + +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.Objects; diff --git a/src/main/java/subway/domain/Station.java b/src/main/java/subway/domain/station/Station.java similarity index 93% rename from src/main/java/subway/domain/Station.java rename to src/main/java/subway/domain/station/Station.java index e271ccd70..19832025a 100644 --- a/src/main/java/subway/domain/Station.java +++ b/src/main/java/subway/domain/station/Station.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.domain.station; public class Station { diff --git a/src/main/java/subway/domain/Stations.java b/src/main/java/subway/domain/station/Stations.java similarity index 96% rename from src/main/java/subway/domain/Stations.java rename to src/main/java/subway/domain/station/Stations.java index fda14cf27..9a2d98967 100644 --- a/src/main/java/subway/domain/Stations.java +++ b/src/main/java/subway/domain/station/Stations.java @@ -1,4 +1,6 @@ -package subway.domain; +package subway.domain.station; + +import subway.domain.Distance; public class Stations { diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index c9554f09e..0af445bdf 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -4,7 +4,7 @@ import org.springframework.transaction.annotation.Transactional; import subway.dao.LineDao; import subway.dao.LineEntity; -import subway.domain.Line; +import subway.domain.line.Line; import subway.global.exception.line.CanNotFoundLineException; import java.util.List; diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index f8fad58ce..33022a3d4 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,12 +1,12 @@ package subway.service; import org.springframework.stereotype.Service; -import subway.domain.ChargePolicyComposite; -import subway.domain.DiscountCondition; -import subway.domain.Line; import subway.domain.Money; -import subway.domain.Route; -import subway.domain.Station; +import subway.domain.line.Line; +import subway.domain.policy.ChargePolicyComposite; +import subway.domain.policy.discount.DiscountCondition; +import subway.domain.route.Route; +import subway.domain.station.Station; import subway.service.dto.ShortestRouteRequest; import java.util.List; diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/service/SectionCommandService.java index 17121c43b..3ba8cc668 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/service/SectionCommandService.java @@ -3,9 +3,9 @@ import org.springframework.stereotype.Service; import subway.dao.SectionDao; import subway.dao.SectionEntity; -import subway.domain.Section; -import subway.domain.Station; -import subway.domain.Stations; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import subway.global.exception.section.CanNotDuplicatedSectionException; import java.util.List; diff --git a/src/main/java/subway/service/SectionQueryService.java b/src/main/java/subway/service/SectionQueryService.java index 1ed00891a..239e79e94 100644 --- a/src/main/java/subway/service/SectionQueryService.java +++ b/src/main/java/subway/service/SectionQueryService.java @@ -3,9 +3,9 @@ import org.springframework.stereotype.Service; import subway.dao.SectionDao; import subway.dao.SectionEntity; -import subway.domain.Section; -import subway.domain.Station; -import subway.domain.Stations; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java index 17909a665..7266dffb2 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/service/StationService.java @@ -2,10 +2,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.domain.Line; -import subway.domain.Section; -import subway.domain.Station; -import subway.domain.Stations; +import subway.domain.line.Line; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import subway.service.dto.StationDeleteRequest; import subway.service.dto.StationRegisterRequest; diff --git a/src/test/java/subway/domain/LineTest.java b/src/test/java/subway/domain/LineTest.java index c2041019d..7670c10a2 100644 --- a/src/test/java/subway/domain/LineTest.java +++ b/src/test/java/subway/domain/LineTest.java @@ -2,6 +2,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import subway.domain.line.Line; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.List; diff --git a/src/test/java/subway/domain/RouteTest.java b/src/test/java/subway/domain/RouteTest.java index abd9c2c2d..7fe17eeb4 100644 --- a/src/test/java/subway/domain/RouteTest.java +++ b/src/test/java/subway/domain/RouteTest.java @@ -5,6 +5,12 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import subway.domain.line.Line; +import subway.domain.route.EdgeSection; +import subway.domain.route.Route; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.List; import java.util.stream.Collectors; diff --git a/src/test/java/subway/domain/SectionTest.java b/src/test/java/subway/domain/SectionTest.java index a9e740987..6508afe78 100644 --- a/src/test/java/subway/domain/SectionTest.java +++ b/src/test/java/subway/domain/SectionTest.java @@ -2,6 +2,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; diff --git a/src/test/java/subway/domain/StationTest.java b/src/test/java/subway/domain/StationTest.java index a034818c2..834b8a486 100644 --- a/src/test/java/subway/domain/StationTest.java +++ b/src/test/java/subway/domain/StationTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import subway.domain.station.Station; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/src/test/java/subway/domain/StationsTest.java b/src/test/java/subway/domain/StationsTest.java index fd8652629..9d52fe8f9 100644 --- a/src/test/java/subway/domain/StationsTest.java +++ b/src/test/java/subway/domain/StationsTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import subway.domain.station.Station; +import subway.domain.station.Stations; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/src/test/java/subway/domain/ChargePolicyCompositeTest.java b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java similarity index 86% rename from src/test/java/subway/domain/ChargePolicyCompositeTest.java rename to src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java index a9b97d230..bf665dce0 100644 --- a/src/test/java/subway/domain/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java @@ -1,8 +1,18 @@ -package subway.domain; +package subway.domain.policy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import subway.domain.Money; +import subway.domain.line.Line; +import subway.domain.policy.discount.AgeDiscountPolicy; +import subway.domain.policy.discount.DiscountCondition; +import subway.domain.policy.fare.DefaultFarePolicy; +import subway.domain.policy.fare.LineFarePolicy; +import subway.domain.route.Route; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.List; diff --git a/src/test/java/subway/domain/DefaultPricePolicyTest.java b/src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java similarity index 93% rename from src/test/java/subway/domain/DefaultPricePolicyTest.java rename to src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java index 72a80f240..55d0d888a 100644 --- a/src/test/java/subway/domain/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java @@ -1,10 +1,16 @@ -package subway.domain; +package subway.domain.policy.fare; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import subway.domain.Money; +import subway.domain.line.Line; +import subway.domain.route.Route; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; import java.util.List; import java.util.stream.Stream; From 6eddf3d37956ec2d0b834f0f2cfe20f8a3474f6b Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 17:19:05 +0900 Subject: [PATCH 11/41] =?UTF-8?q?refactor=20:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/exception/common/ExceptionHandlerController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/subway/global/exception/common/ExceptionHandlerController.java b/src/main/java/subway/global/exception/common/ExceptionHandlerController.java index 92bee34fa..17b0dd462 100644 --- a/src/main/java/subway/global/exception/common/ExceptionHandlerController.java +++ b/src/main/java/subway/global/exception/common/ExceptionHandlerController.java @@ -33,7 +33,7 @@ public ResponseEntity handleUnexpectedException(Exception exc errorLogging(exception); return ResponseEntity.internalServerError() - .body(new ExceptionResponse("전화 주세요")); + .body(new ExceptionResponse(String.format("전화 주세요 : %s", exception.getMessage()))); } @ExceptionHandler(DataAccessResourceFailureException.class) From a42f94a7ddf1cc9fb2a5c2c5f3129b6f2cd98ae5 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 17:26:34 +0900 Subject: [PATCH 12/41] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/service/LineQueryService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index 0af445bdf..24e551707 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -28,7 +28,7 @@ public List searchLines(final String lineName) { return searchAllLine(); } - return List.of(searchSpecificLine(lineName)); + return List.of(searchByLineName(lineName)); } public List searchAllLine() { @@ -43,10 +43,6 @@ public List searchAllLine() { .collect(Collectors.toList()); } - private Line searchSpecificLine(final String lineName) { - return searchByLineName(lineName); - } - public Line searchByLineName(final String lineName) { final LineEntity lineEntity = lineDao.findByLineName(lineName) From aa0e619147ff6ac106e6c2d1197f210c794473ca Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 18:14:19 +0900 Subject: [PATCH 13/41] =?UTF-8?q?feat=20:=20line=20id=20=EB=A1=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20API=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/controller/LineController.java | 8 ++++++++ src/main/java/subway/dao/LineDao.java | 10 ++++++++++ src/main/java/subway/service/LineQueryService.java | 13 +++++++++++++ 3 files changed, 31 insertions(+) diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index 30f835c6d..0aa65d804 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -2,6 +2,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; @@ -38,6 +39,13 @@ public List showLines(@RequestParam(value = "lineName", required = .collect(Collectors.toList()); } + @GetMapping("/lines/{line-id}") + public LineResponse showLines(@PathVariable("line-id") Long lineId) { + final Line line = lineQueryService.searchByLineId(lineId); + + return new LineResponse(line.getName(), mapToSectionResponseFrom(line)); + } + @PostMapping("/lines") @ResponseStatus(HttpStatus.CREATED) public LineResponse registerLine(@RequestBody RegisterLineRequest registerLineRequest) { diff --git a/src/main/java/subway/dao/LineDao.java b/src/main/java/subway/dao/LineDao.java index 795774b5b..8901803f5 100644 --- a/src/main/java/subway/dao/LineDao.java +++ b/src/main/java/subway/dao/LineDao.java @@ -45,6 +45,16 @@ public List findAll() { return jdbcTemplate.query(sql, rowMapper); } + public Optional findByLineId(final Long lineId) { + final String sql = "SELECT * FROM LINE L WHERE L.id = ?"; + + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(sql, rowMapper, lineId)); + } catch (EmptyResultDataAccessException exception) { + return Optional.empty(); + } + } + public void deleteById(final Long lineId) { final String sql = "DELETE FROM LINE L WHERE L.id = ?"; diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index 24e551707..fe10378e9 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -55,6 +55,19 @@ public Line searchByLineName(final String lineName) { ); } + public Line searchByLineId(final Long lineId) { + + final LineEntity lineEntity = + lineDao.findByLineId(lineId) + .orElseThrow(() -> new CanNotFoundLineException("해당 노선은 존재하지 않습니다.")); + + return new Line( + lineEntity.getId(), + lineEntity.getName(), + sectionQueryService.searchSectionsByLineId(lineEntity.getId()) + ); + } + public boolean isExistLine(final String lineName) { return lineDao.findByLineName(lineName).isPresent(); } From 781c56954d7332e4f7aa563758d89edea69dae7f Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 18:17:32 +0900 Subject: [PATCH 14/41] =?UTF-8?q?refactor=20:=20line=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EC=8B=9C=20id=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/controller/LineController.java | 6 +++--- src/main/java/subway/service/dto/LineResponse.java | 8 +++++++- ...ultPricePolicyTest.java => DefaultFarePolicyTest.java} | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) rename src/test/java/subway/domain/policy/fare/{DefaultPricePolicyTest.java => DefaultFarePolicyTest.java} (99%) diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index 0aa65d804..3f1c9bc44 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -35,7 +35,7 @@ public List showLines(@RequestParam(value = "lineName", required = final List lines = lineQueryService.searchLines(lineName); return lines.stream() - .map(line -> new LineResponse(line.getName(), mapToSectionResponseFrom(line))) + .map(line -> new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId())) .collect(Collectors.toList()); } @@ -43,7 +43,7 @@ public List showLines(@RequestParam(value = "lineName", required = public LineResponse showLines(@PathVariable("line-id") Long lineId) { final Line line = lineQueryService.searchByLineId(lineId); - return new LineResponse(line.getName(), mapToSectionResponseFrom(line)); + return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); } @PostMapping("/lines") @@ -53,7 +53,7 @@ public LineResponse registerLine(@RequestBody RegisterLineRequest registerLineRe final Line line = lineQueryService.searchByLineName(registerLineRequest.getLineName()); - return new LineResponse(line.getName(), mapToSectionResponseFrom(line)); + return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); } private List mapToSectionResponseFrom(final Line line) { diff --git a/src/main/java/subway/service/dto/LineResponse.java b/src/main/java/subway/service/dto/LineResponse.java index 67e1bd594..5208f9111 100644 --- a/src/main/java/subway/service/dto/LineResponse.java +++ b/src/main/java/subway/service/dto/LineResponse.java @@ -6,10 +6,12 @@ public class LineResponse { private final String lineName; private final List sections; + private final Long lineId; - public LineResponse(final String lineName, final List sections) { + public LineResponse(final String lineName, final List sections, final Long lineId) { this.lineName = lineName; this.sections = sections; + this.lineId = lineId; } public String getLineName() { @@ -19,4 +21,8 @@ public String getLineName() { public List getSections() { return sections; } + + public Long getLineId() { + return lineId; + } } diff --git a/src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java b/src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java similarity index 99% rename from src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java rename to src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java index 55d0d888a..df22479e8 100644 --- a/src/test/java/subway/domain/policy/fare/DefaultPricePolicyTest.java +++ b/src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java @@ -17,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class DefaultPricePolicyTest { +class DefaultFarePolicyTest { private SubwayFarePolicy subwayFarePolicy; From 71c678527fb6b291a24d6b93e213da41dae94bef Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 18:31:25 +0900 Subject: [PATCH 15/41] =?UTF-8?q?refactor=20:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/subway/domain/{ => line}/LineTest.java | 3 +-- src/test/java/subway/domain/{ => route}/RouteTest.java | 5 ++--- src/test/java/subway/domain/{ => station}/StationTest.java | 3 +-- src/test/java/subway/domain/{ => station}/StationsTest.java | 4 +--- 4 files changed, 5 insertions(+), 10 deletions(-) rename src/test/java/subway/domain/{ => line}/LineTest.java (99%) rename src/test/java/subway/domain/{ => route}/RouteTest.java (98%) rename src/test/java/subway/domain/{ => station}/StationTest.java (88%) rename src/test/java/subway/domain/{ => station}/StationsTest.java (87%) diff --git a/src/test/java/subway/domain/LineTest.java b/src/test/java/subway/domain/line/LineTest.java similarity index 99% rename from src/test/java/subway/domain/LineTest.java rename to src/test/java/subway/domain/line/LineTest.java index 7670c10a2..c16d338aa 100644 --- a/src/test/java/subway/domain/LineTest.java +++ b/src/test/java/subway/domain/line/LineTest.java @@ -1,8 +1,7 @@ -package subway.domain; +package subway.domain.line; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import subway.domain.line.Line; import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; diff --git a/src/test/java/subway/domain/RouteTest.java b/src/test/java/subway/domain/route/RouteTest.java similarity index 98% rename from src/test/java/subway/domain/RouteTest.java rename to src/test/java/subway/domain/route/RouteTest.java index 7fe17eeb4..d28fd1e39 100644 --- a/src/test/java/subway/domain/RouteTest.java +++ b/src/test/java/subway/domain/route/RouteTest.java @@ -1,13 +1,12 @@ -package subway.domain; +package subway.domain.route; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import subway.domain.Distance; import subway.domain.line.Line; -import subway.domain.route.EdgeSection; -import subway.domain.route.Route; import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; diff --git a/src/test/java/subway/domain/StationTest.java b/src/test/java/subway/domain/station/StationTest.java similarity index 88% rename from src/test/java/subway/domain/StationTest.java rename to src/test/java/subway/domain/station/StationTest.java index 834b8a486..5d717a4f8 100644 --- a/src/test/java/subway/domain/StationTest.java +++ b/src/test/java/subway/domain/station/StationTest.java @@ -1,8 +1,7 @@ -package subway.domain; +package subway.domain.station; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import subway.domain.station.Station; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/src/test/java/subway/domain/StationsTest.java b/src/test/java/subway/domain/station/StationsTest.java similarity index 87% rename from src/test/java/subway/domain/StationsTest.java rename to src/test/java/subway/domain/station/StationsTest.java index 9d52fe8f9..59fedce81 100644 --- a/src/test/java/subway/domain/StationsTest.java +++ b/src/test/java/subway/domain/station/StationsTest.java @@ -1,9 +1,7 @@ -package subway.domain; +package subway.domain.station; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import subway.domain.station.Station; -import subway.domain.station.Stations; import static org.junit.jupiter.api.Assertions.assertTrue; From 4bcca05ee964b1755eb630065b6a96a3e9f303a2 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 18:31:46 +0900 Subject: [PATCH 16/41] =?UTF-8?q?refactor=20:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/subway/domain/{ => section}/SectionTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/test/java/subway/domain/{ => section}/SectionTest.java (99%) diff --git a/src/test/java/subway/domain/SectionTest.java b/src/test/java/subway/domain/section/SectionTest.java similarity index 99% rename from src/test/java/subway/domain/SectionTest.java rename to src/test/java/subway/domain/section/SectionTest.java index 6508afe78..7247fa926 100644 --- a/src/test/java/subway/domain/SectionTest.java +++ b/src/test/java/subway/domain/section/SectionTest.java @@ -1,8 +1,7 @@ -package subway.domain; +package subway.domain.section; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; From 13d1d2dcdff9ed521ef2816e76aa99d891779e6e Mon Sep 17 00:00:00 2001 From: java-saeng Date: Sun, 21 May 2023 18:53:25 +0900 Subject: [PATCH 17/41] =?UTF-8?q?test=20:=20LineDao=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/subway/dao/LineDaoTest.java | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/test/java/subway/dao/LineDaoTest.java diff --git a/src/test/java/subway/dao/LineDaoTest.java b/src/test/java/subway/dao/LineDaoTest.java new file mode 100644 index 000000000..8328749aa --- /dev/null +++ b/src/test/java/subway/dao/LineDaoTest.java @@ -0,0 +1,109 @@ +package subway.dao; + +import org.assertj.core.api.Assertions; +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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class LineDaoTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + private LineDao lineDao; + + @BeforeEach + void setUp() { + lineDao = new LineDao(jdbcTemplate); + } + + @Test + @DisplayName("findByLineName() : 라인 이름으로 라인을 찾을 수 있다.") + void test_findByLineName() throws Exception { + //given + final String lineName = "1호선"; + + //when + final Optional savedLine = lineDao.findByLineName(lineName); + + //then + assertAll( + () -> assertThat(savedLine).isPresent(), + () -> assertEquals(1L, savedLine.get().getId()), + () -> assertEquals(savedLine.get().getName(), lineName) + ); + } + + @Test + @DisplayName("findAll() : 모든 라인을 찾을 수 있다.") + void test_findAll() throws Exception { + //when + final List lineEntities = lineDao.findAll(); + + //then + assertEquals(2, lineEntities.size()); + } + + @Test + @DisplayName("findByLineId() : 라인 id로 라인을 찾을 수 있다.") + void test_findByLineId() throws Exception { + //given + final Long lineId = 2L; + + //when + final Optional savedLine = lineDao.findByLineId(lineId); + + //then + assertAll( + () -> Assertions.assertThat(savedLine).isPresent(), + () -> assertEquals(2L, savedLine.get().getId()), + () -> assertEquals("2호선", savedLine.get().getName()) + ); + } + + @Test + @DisplayName("deleteById() : 라인 id로 라인을 삭제할 수 있다.") + void test_deleteById() throws Exception { + //given + final Long lineId = 2L; + + final int beforeSize = lineDao.findAll().size(); + + //when + lineDao.deleteById(lineId); + + //then + final int afterSize = lineDao.findAll().size(); + assertEquals(afterSize, beforeSize - 1); + } + + @Test + @DisplayName("save() : 라인을 저장할 수 있다.") + void test_save() throws Exception { + //given + final LineEntity lineEntity = new LineEntity("newLine"); + + final int beforeSize = lineDao.findAll().size(); + + //when + lineDao.save(lineEntity); + + //then + final int afterSize = lineDao.findAll().size(); + + assertEquals(afterSize, beforeSize + 1); + } +} From 19f4307347f168a907b527c6fde2b8fb3fdf4a52 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 00:02:25 +0900 Subject: [PATCH 18/41] =?UTF-8?q?test=20:=20SectionDao=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/subway/dao/SectionDaoTest.java | 136 +++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/test/java/subway/dao/SectionDaoTest.java diff --git a/src/test/java/subway/dao/SectionDaoTest.java b/src/test/java/subway/dao/SectionDaoTest.java new file mode 100644 index 000000000..53507ed92 --- /dev/null +++ b/src/test/java/subway/dao/SectionDaoTest.java @@ -0,0 +1,136 @@ +package subway.dao; + +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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class SectionDaoTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + private SectionDao sectionDao; + + @BeforeEach + void setUp() { + sectionDao = new SectionDao(jdbcTemplate); + } + + @Test + @DisplayName("save() : section을 저장할 수 있다.") + void test_save() throws Exception { + //given + final String currentStationName = "H"; + final String nextStationName = "Z"; + final int distance = 1; + final long lineId = 2L; + + final SectionEntity sectionEntity = new SectionEntity( + currentStationName, + nextStationName, + distance, + lineId + ); + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionDao.save(sectionEntity); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("findSectionsByLineId() : 라인에 속한 모든 section을 조회할 수 있다.") + void test_findSectionsByLineId() throws Exception { + //given + final long lineId = 2L; + + //when + final int size = sectionDao.findSectionsByLineId(lineId).size(); + + //then + assertEquals(4, size); + } + + @Test + @DisplayName("deleteAll() : 라인에 포함되있는 section을 모두 삭제할 수 있다.") + void test_deleteAll() throws Exception { + //given + final long lineId = 2L; + + //when + sectionDao.deleteAll(lineId); + + //then + assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); + } + + @Test + @DisplayName("update() : id를 통해 세션의 정보를 수정할 수 있다.") + void test_update() throws Exception { + //given + final Long sectionId = 7L; + final String updatedCurrentStationName = "Z"; + final String updatedNextStationName = "K"; + final int updatedDistance = 3; + final long lineId = 2L; + + final SectionEntity updatedSectionEntity = new SectionEntity( + 7L, + updatedCurrentStationName, + updatedNextStationName, + updatedDistance, + lineId + ); + + //when + sectionDao.update(updatedSectionEntity); + + //then + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(lineId) + .stream() + .filter(it -> it.getId().equals(sectionId)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals(sectionEntity.getDistance(), updatedSectionEntity.getDistance()), + () -> assertEquals(sectionEntity.getCurrentStationName(), + updatedSectionEntity.getCurrentStationName()), + () -> assertEquals(sectionEntity.getNextStationName(), + updatedSectionEntity.getNextStationName()) + ); + } + + @Test + @DisplayName("deleteById() : id를 통해 section을 삭제할 수 있다.") + void test_deleteById() throws Exception { + //given + final long sectionId = 1L; + final long lineId = 1L; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionDao.deleteById(sectionId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize - 1); + } +} From 074f8966ba812e02ef10649f64440d9276e666e9 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 00:35:32 +0900 Subject: [PATCH 19/41] =?UTF-8?q?test=20:=20LineControllerTest=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/controller/LineController.java | 4 +- .../service/dto/RegisterLineRequest.java | 15 ++ .../subway/controller/LineControllerTest.java | 142 ++++++++++++++++++ 3 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 src/test/java/subway/controller/LineControllerTest.java diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index 3f1c9bc44..2a110476b 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -31,7 +31,7 @@ public LineController(final LineCommandService lineCommandService, final LineQue @GetMapping("/lines") @ResponseStatus(HttpStatus.OK) - public List showLines(@RequestParam(value = "lineName", required = false) String lineName) { + public List showLine(@RequestParam(value = "lineName", required = false) String lineName) { final List lines = lineQueryService.searchLines(lineName); return lines.stream() @@ -40,7 +40,7 @@ public List showLines(@RequestParam(value = "lineName", required = } @GetMapping("/lines/{line-id}") - public LineResponse showLines(@PathVariable("line-id") Long lineId) { + public LineResponse showLine(@PathVariable("line-id") Long lineId) { final Line line = lineQueryService.searchByLineId(lineId); return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); diff --git a/src/main/java/subway/service/dto/RegisterLineRequest.java b/src/main/java/subway/service/dto/RegisterLineRequest.java index 5a1a0f3a3..895010eb4 100644 --- a/src/main/java/subway/service/dto/RegisterLineRequest.java +++ b/src/main/java/subway/service/dto/RegisterLineRequest.java @@ -7,6 +7,21 @@ public class RegisterLineRequest { private String lineName; private int distance; + private RegisterLineRequest() { + } + + public RegisterLineRequest( + final String currentStationName, + final String nextStationName, + final String lineName, + final int distance + ) { + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.lineName = lineName; + this.distance = distance; + } + public String getCurrentStationName() { return currentStationName; } diff --git a/src/test/java/subway/controller/LineControllerTest.java b/src/test/java/subway/controller/LineControllerTest.java new file mode 100644 index 000000000..74742b868 --- /dev/null +++ b/src/test/java/subway/controller/LineControllerTest.java @@ -0,0 +1,142 @@ +package subway.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import subway.domain.line.Line; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; +import subway.service.LineCommandService; +import subway.service.LineQueryService; +import subway.service.dto.RegisterLineRequest; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(LineController.class) +class LineControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private LineCommandService lineCommandService; + + @MockBean + private LineQueryService lineQueryService; + + @Test + @DisplayName("showLines() : lineName이 주어지면 해당 line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLines() throws Exception { + //given + final String lineName = "2호선"; + + final List lines = createDefaultLines(); + + when(lineQueryService.searchLines(any())) + .thenReturn(lines); + + //when & then + mockMvc.perform(get("/lines?lineName={lineName}", lineName)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("showLines() : lineName이 주어지지 않으면 모든 line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLines_all() throws Exception { + //given + final List lines = createDefaultLines(); + + when(lineQueryService.searchLines(any())) + .thenReturn(lines); + + //when & then + mockMvc.perform(get("/lines")) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("showLine() : id를 통해 해당 Line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLine() throws Exception { + //given + final List lines = createDefaultLines(); + final long lineId = 1L; + + when(lineQueryService.searchByLineId(anyLong())) + .thenReturn(lines.get(0)); + + //when & then + mockMvc.perform(get("/lines/{line-id}", lineId)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("registerLine() : Line을 성공적으로 저장할 때 201 Created를 반환한다.") + void test_registerLine() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "B"; + final String lineName = "line"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + final String bodyData = objectMapper.writeValueAsString(registerLineRequest); + + doNothing().when(lineCommandService) + .registerLine(any()); + + when(lineQueryService.searchByLineName(any())) + .thenReturn(createDefaultLines().get(0)); + + //when & then + mockMvc.perform(post("/lines") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isCreated()); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } +} From 35ea99126f0c8e455b54882b360e7436a2e405a7 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 01:16:14 +0900 Subject: [PATCH 20/41] =?UTF-8?q?test=20:=20RouteControllerTest=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/RouteControllerTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/java/subway/controller/RouteControllerTest.java diff --git a/src/test/java/subway/controller/RouteControllerTest.java b/src/test/java/subway/controller/RouteControllerTest.java new file mode 100644 index 000000000..88d36b443 --- /dev/null +++ b/src/test/java/subway/controller/RouteControllerTest.java @@ -0,0 +1,79 @@ +package subway.controller; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; +import subway.service.RouteQueryService; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(RouteController.class) +class RouteControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private RouteQueryService routeQueryService; + + @Test + @DisplayName("showShortestRoute() : 출발, 도착역이 주어지고, 나이가 주어지지 않으면 추가 요금 없이 최단 경로와 가격을 조회되면 200 OK를 반환한다.") + void test_showShortestRoute() throws Exception { + //given + final String startStationName = "A"; + final String endStationName = "B"; + + final List shortestRoute = List.of("A", "K", "Z", "B"); + final double leastCost = 100d; + final int shortestDistance = 10; + + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRoute); + + when(routeQueryService.searchLeastCost(any())) + .thenReturn(leastCost); + + when(routeQueryService.searchShortestDistance(any())) + .thenReturn(shortestDistance); + + //then + mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}", + startStationName, endStationName)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("showShortestRoute() : 나이가 주어지면 나이에 따른 요금이 추가된 최단 경로와 가격을 조회되면 200 OK를 반환한다.") + void test_showShortestRoute_age() throws Exception { + //given + final String startStationName = "A"; + final String endStationName = "B"; + final Integer age = 14; + + final List shortestRoute = List.of("A", "K", "Z", "B"); + final double leastCost = 100d; + final int shortestDistance = 10; + + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRoute); + + when(routeQueryService.searchLeastCost(any())) + .thenReturn(leastCost); + + when(routeQueryService.searchShortestDistance(any())) + .thenReturn(shortestDistance); + + //then + mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}&age={age}", + startStationName, endStationName, age)) + .andExpect(status().isOk()); + } +} From ff4297efb425b28002afaeb6bfce439281f638c3 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 01:22:58 +0900 Subject: [PATCH 21/41] =?UTF-8?q?test=20:=20StationController=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 삭제 시 No Content 로 수정 --- .../subway/controller/StationController.java | 1 + .../service/dto/StationDeleteRequest.java | 8 ++ .../service/dto/StationRegisterRequest.java | 15 ++++ .../controller/StationControllerTest.java | 77 +++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 src/test/java/subway/controller/StationControllerTest.java diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java index 7819db5e3..a7c76cb2d 100644 --- a/src/main/java/subway/controller/StationController.java +++ b/src/main/java/subway/controller/StationController.java @@ -32,6 +32,7 @@ public StationRegisterResponse registerStation(@RequestBody StationRegisterReque } @DeleteMapping("/stations") + @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteStation(@RequestBody StationDeleteRequest stationDeleteRequest) { stationService.deleteStation(stationDeleteRequest); } diff --git a/src/main/java/subway/service/dto/StationDeleteRequest.java b/src/main/java/subway/service/dto/StationDeleteRequest.java index 0c912d212..db194a244 100644 --- a/src/main/java/subway/service/dto/StationDeleteRequest.java +++ b/src/main/java/subway/service/dto/StationDeleteRequest.java @@ -5,6 +5,14 @@ public class StationDeleteRequest { private String lineName; private String stationName; + private StationDeleteRequest() { + } + + public StationDeleteRequest(final String lineName, final String stationName) { + this.lineName = lineName; + this.stationName = stationName; + } + public String getLineName() { return lineName; } diff --git a/src/main/java/subway/service/dto/StationRegisterRequest.java b/src/main/java/subway/service/dto/StationRegisterRequest.java index b52586fa2..8620cf6a8 100644 --- a/src/main/java/subway/service/dto/StationRegisterRequest.java +++ b/src/main/java/subway/service/dto/StationRegisterRequest.java @@ -7,6 +7,21 @@ public class StationRegisterRequest { private String nextStationName; private int distance; + private StationRegisterRequest() { + } + + public StationRegisterRequest( + final String lineName, + final String currentStationName, + final String nextStationName, + final int distance + ) { + this.lineName = lineName; + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.distance = distance; + } + public String getLineName() { return lineName; } diff --git a/src/test/java/subway/controller/StationControllerTest.java b/src/test/java/subway/controller/StationControllerTest.java new file mode 100644 index 000000000..a1333188d --- /dev/null +++ b/src/test/java/subway/controller/StationControllerTest.java @@ -0,0 +1,77 @@ +package subway.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import subway.service.StationService; +import subway.service.dto.StationDeleteRequest; +import subway.service.dto.StationRegisterRequest; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(StationController.class) +class StationControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private StationService stationService; + + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("registerStation() : station이 정상적으로 저장되면 201 Created를 반환한다.") + void test_registerStation() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "B"; + final String lineName = "line"; + final int distance = 4; + + final StationRegisterRequest stationRegisterRequest = + new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); + + final String bodyData = objectMapper.writeValueAsString(stationRegisterRequest); + + doNothing().when(stationService) + .registerStation(any()); + + //when & then + mockMvc.perform(post("/stations") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isCreated()); + } + + @Test + @DisplayName("deleteStation() : station 이 정상적으로 삭제되면 204 No Content 를 반환한다.") + void test_deleteStation() throws Exception { + //given + final String lineName = "line"; + final String stationName = "station"; + + final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName); + + final String bodyData = objectMapper.writeValueAsString(stationDeleteRequest); + + doNothing().when(stationService) + .deleteStation(any()); + + //when & then + mockMvc.perform(delete("/stations") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isNoContent()); + } +} From 9c12f91930b3c886cfbf2efa6bd8511990788a73 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 01:41:50 +0900 Subject: [PATCH 22/41] =?UTF-8?q?test=20:=20LineCommandService=20Integrati?= =?UTF-8?q?on=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-test.yml | 13 ++- .../java/helper/IntegrationTestHelper.java | 10 +++ .../service/LineCommandServiceTest.java | 79 +++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/test/java/helper/IntegrationTestHelper.java create mode 100644 src/test/java/subway/service/LineCommandServiceTest.java diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index fd2c8d374..d8396c62d 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -39,7 +39,16 @@ spring: sql: init: mode: never - profiles: - active: --- + +spring: + datasource: + url: jdbc:h2:mem:testdb;MODE=MySQL + driver-class-name: org.h2.Driver + config: + activate: + on-profile: integration + sql: + init: + mode: always diff --git a/src/test/java/helper/IntegrationTestHelper.java b/src/test/java/helper/IntegrationTestHelper.java new file mode 100644 index 000000000..4662e9e0a --- /dev/null +++ b/src/test/java/helper/IntegrationTestHelper.java @@ -0,0 +1,10 @@ +package helper; + + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest +@ActiveProfiles({"test", "integration"}) +public class IntegrationTestHelper { +} diff --git a/src/test/java/subway/service/LineCommandServiceTest.java b/src/test/java/subway/service/LineCommandServiceTest.java new file mode 100644 index 000000000..f4dd0c0f0 --- /dev/null +++ b/src/test/java/subway/service/LineCommandServiceTest.java @@ -0,0 +1,79 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.dao.LineDao; +import subway.dao.LineEntity; +import subway.global.exception.line.CanNotDuplicatedLineNameException; +import subway.service.dto.RegisterLineRequest; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LineCommandServiceTest extends IntegrationTestHelper { + + @Autowired + private LineCommandService lineCommandService; + + @Autowired + private LineDao lineDao; + + @Test + @DisplayName("deleteLine() : line id 가 주어졌을 때 해당 라인을 삭제할 수 있다.") + void test_deleteLine() throws Exception { + //given + final long lineId = 1L; + + //when + lineCommandService.deleteLine(lineId); + + //then + final Optional savedLine = lineDao.findByLineId(lineId); + + assertThat(savedLine).isEmpty(); + } + + @Test + @DisplayName("registerLine() : 새로운 line을 생성할 수 있다.") + void test_registerLine() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final String lineName = "line"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + final int beforeSize = lineDao.findAll().size(); + + //when + lineCommandService.registerLine(registerLineRequest); + + //then + final int afterSize = lineDao.findAll().size(); + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("registerLine() : line을 새로 생성할 때, 기존에 있는 lineName이 존재한다면 CanNotDuplicatedLineNameException이 발생한다.") + void test_registerLine_CanNotDuplicatedLineNameException() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final String lineName = "1호선"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + //when & then + assertThatThrownBy(() -> lineCommandService.registerLine(registerLineRequest)) + .isInstanceOf(CanNotDuplicatedLineNameException.class); + } +} From e90d594846ef054f43c9601b27b19bab32d0eead Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 01:50:10 +0900 Subject: [PATCH 23/41] =?UTF-8?q?test=20:=20LineQueryService=20Integration?= =?UTF-8?q?=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/subway/service/LineQueryService.java | 1 + .../subway/service/LineQueryServiceTest.java | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/test/java/subway/service/LineQueryServiceTest.java diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index fe10378e9..38cb5bb4d 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -69,6 +69,7 @@ public Line searchByLineId(final Long lineId) { } public boolean isExistLine(final String lineName) { + //TODO : Line 에 이름 인덱스 생성해보기 return lineDao.findByLineName(lineName).isPresent(); } } diff --git a/src/test/java/subway/service/LineQueryServiceTest.java b/src/test/java/subway/service/LineQueryServiceTest.java new file mode 100644 index 000000000..031bc47fc --- /dev/null +++ b/src/test/java/subway/service/LineQueryServiceTest.java @@ -0,0 +1,97 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.springframework.beans.factory.annotation.Autowired; +import subway.domain.line.Line; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LineQueryServiceTest extends IntegrationTestHelper { + + @Autowired + private LineQueryService lineQueryService; + + @Test + @DisplayName("searchLines() : lineName이 존재하지 않으면 모든 line을 조회할 수 있다.") + void test_searchLines_all() throws Exception { + //given + final String lineName = null; + + //when + final List lines = lineQueryService.searchLines(lineName); + + //then + assertEquals(2, lines.size()); + } + + @Test + @DisplayName("searchLines() : lineName을 통해 해당 line을 조회할 수 있다.") + void test_searchLines() throws Exception { + //given + final String lineName = "1호선"; + + //when + final List lines = lineQueryService.searchLines(lineName); + + //then + assertAll( + () -> assertEquals(1, lines.size()), + () -> assertEquals(lines.get(0).getName(), lineName) + ); + } + + @Test + @DisplayName("searchAllLine() : 모든 Line을 조회할 수 있다.") + void test_searchAllLine() throws Exception { + //when + final List lines = lineQueryService.searchAllLine(); + + //then + assertEquals(2, lines.size()); + } + + @Test + @DisplayName("searchByLineName() : lineName을 통해 해당 line을 조회할 수 있다.") + void test_searchByLineName() throws Exception { + //given + final String lineName = "1호선"; + + //when + final Line line = lineQueryService.searchByLineName(lineName); + + //then + assertEquals(line.getName(), lineName); + } + + @Test + @DisplayName("searchByLineId() : line id를 통해 해당 line을 조회할 수 있다.") + void test_searchByLineId() throws Exception { + //given + final Long lineId = 1L; + + //when + final Line line = lineQueryService.searchByLineId(lineId); + + //then + assertEquals(line.getId(), lineId); + } + + @ParameterizedTest + @CsvSource({ + "1호선, true", + "2호선, true", + "3호선, false" + }) + @DisplayName("isExistLine() : lineName을 통해 해당 line이 존재하는지 알 수 있다.") + void test_isExistLine(final String lineName, final boolean isExist) throws Exception { + //then + assertEquals(isExist, lineQueryService.isExistLine(lineName)); + } +} From 028a82a0d2a19a30cf796b13c088f3591877003d Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 02:05:11 +0900 Subject: [PATCH 24/41] =?UTF-8?q?test=20:=20RouteQueryService=20Integratio?= =?UTF-8?q?n=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/service/RouteQueryService.java | 1 - .../subway/service/RouteQueryServiceTest.java | 73 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/java/subway/service/RouteQueryServiceTest.java diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 33022a3d4..bcc406240 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -65,5 +65,4 @@ public int searchShortestDistance(final ShortestRouteRequest shortestRouteReques return route.findShortestRouteDistance() .getValue(); } - } diff --git a/src/test/java/subway/service/RouteQueryServiceTest.java b/src/test/java/subway/service/RouteQueryServiceTest.java new file mode 100644 index 000000000..d274a0217 --- /dev/null +++ b/src/test/java/subway/service/RouteQueryServiceTest.java @@ -0,0 +1,73 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.service.dto.ShortestRouteRequest; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RouteQueryServiceTest extends IntegrationTestHelper { + + @Autowired + private RouteQueryService routeQueryService; + + @Test + @DisplayName("searchShortestRoute() : 출발, 도착역을 통해 최소 경로를 조회할 수 있다.") + void test_searchShortestRoute() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, null); + + //when + final List route = routeQueryService.searchShortestRoute(shortestRouteRequest); + + //then + assertThat(route).containsAnyElementsOf(List.of("A", "B", "C", "D")); + } + + @Test + @DisplayName("searchLeastCost() : 나이와 특정 호선에 따라서 최소 요금 정보를 조회할 수 있다.") + void test_searchLeastCost() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + final Integer age = 14; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, age); + + //when + final double fare = routeQueryService.searchLeastCost(shortestRouteRequest); + + //then + //부과 : 1호선 가격 : 500, 기본 요금 : 1250 + //할인 : 청소년 -350, -20% + assertEquals(1120d, fare); + } + + @Test + @DisplayName("searchShortestDistance() : 출발, 도착역 간의 최소 경로 거리를 조회할 수 있다.") + void test_searchShortestDistance() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + final Integer age = null; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, age); + + //when + final int distance = routeQueryService.searchShortestDistance(shortestRouteRequest); + + //then + assertEquals(6, distance); + } +} From 3927e12373a3ce43328f7e1ea3d9fd4f00543ebe Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 12:26:09 +0900 Subject: [PATCH 25/41] =?UTF-8?q?test=20:=20SectionCommandService=20Integr?= =?UTF-8?q?ation=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/service/SectionCommandService.java | 2 +- .../java/subway/service/StationService.java | 4 +- .../java/helper/IntegrationTestHelper.java | 3 + .../service/SectionCommandServiceTest.java | 119 ++++++++++++++++++ 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/test/java/subway/service/SectionCommandServiceTest.java diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/service/SectionCommandService.java index 3ba8cc668..cd99de49c 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/service/SectionCommandService.java @@ -61,7 +61,7 @@ public void deleteAll(final Long lineId) { sectionDao.deleteAll(lineId); } - public void deleteSection(final Long sectionId) { + public void deleteSectionById(final Long sectionId) { sectionDao.deleteById(sectionId); } diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java index 7266dffb2..371304184 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/service/StationService.java @@ -102,7 +102,7 @@ private Consumer
updateAndDeleteSection( .filter(origin -> updatedSection.stream().noneMatch(origin::isSame)) .filter(origin -> !origin.equals(section)) .findFirst() - .ifPresent(origin -> sectionCommandService.deleteSection(origin.getId())); + .ifPresent(origin -> sectionCommandService.deleteSectionById(origin.getId())); }; } @@ -113,6 +113,6 @@ private Runnable onlyDeleteSection( return () -> originSection.stream() .filter(section -> updatedSection.stream().noneMatch(section::isSame)) .findFirst() - .ifPresent(section -> sectionCommandService.deleteSection(section.getId())); + .ifPresent(section -> sectionCommandService.deleteSectionById(section.getId())); } } diff --git a/src/test/java/helper/IntegrationTestHelper.java b/src/test/java/helper/IntegrationTestHelper.java index 4662e9e0a..0b6230f76 100644 --- a/src/test/java/helper/IntegrationTestHelper.java +++ b/src/test/java/helper/IntegrationTestHelper.java @@ -3,8 +3,11 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; @SpringBootTest @ActiveProfiles({"test", "integration"}) +@Sql(value = "/schema.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) +@Sql(value = "/data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) public class IntegrationTestHelper { } diff --git a/src/test/java/subway/service/SectionCommandServiceTest.java b/src/test/java/subway/service/SectionCommandServiceTest.java new file mode 100644 index 000000000..cd6ae4eab --- /dev/null +++ b/src/test/java/subway/service/SectionCommandServiceTest.java @@ -0,0 +1,119 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.dao.SectionDao; +import subway.dao.SectionEntity; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; +import subway.global.exception.section.CanNotDuplicatedSectionException; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SectionCommandServiceTest extends IntegrationTestHelper { + + @Autowired + private SectionCommandService sectionCommandService; + + @Autowired + private SectionDao sectionDao; + + @Test + @DisplayName("registerSection() : 섹션을 저장할 수 있다.") + void test_registerSection() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final Long lineId = 2L; + final int distance = 4; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionCommandService.registerSection(currentStationName, nextStationName, distance, lineId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("registerSection() : 섹션을 저장할 때, 해당 호선에 같은 섹션이 있으면 CanNotDuplicatedSectionException이 발생한다.") + void test_registerSection_CanNotDuplicatedSectionException() throws Exception { + //given + final String currentStationName = "B"; + final String nextStationName = "F"; + final Long lineId = 2L; + final int distance = 4; + + //when & then + assertThatThrownBy( + () -> sectionCommandService.registerSection(currentStationName, nextStationName, distance, lineId)) + .isInstanceOf(CanNotDuplicatedSectionException.class); + } + + @Test + @DisplayName("deleteAll() : 주어진 호선에 있는 섹션들을 모두 삭제할 수 있다.") + void test_deleteAll() throws Exception { + //given + final long lineId = 1L; + + //when + sectionCommandService.deleteAll(lineId); + + //then + assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); + } + + @Test + @DisplayName("deleteSection() : section id를 통해 섹션을 삭제할 수 있다.") + void test_deleteSection() throws Exception { + //given + final long sectionId = 1L; + final long lineId = 1L; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionCommandService.deleteSectionById(sectionId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize - 1); + } + + @Test + @DisplayName("updateSection() : 해당 섹션을 수정할 수 있다.") + void test_updateSection() throws Exception { + //given + final Stations stations = new Stations(new Station("Z"), new Station("V"), 5); + final long sectionId = 3L; + final Section section = new Section(sectionId, stations); + + //when + sectionCommandService.updateSection(section); + + //then + final SectionEntity updatedSection = + sectionDao.findSectionsByLineId(1L) + .stream() + .filter(it -> it.getId().equals(sectionId)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals(updatedSection.getNextStationName(), section.getStations().getNext().getName()), + () -> assertEquals(updatedSection.getCurrentStationName(), + section.getStations().getCurrent().getName()), + () -> assertEquals(updatedSection.getDistance(), section.getStations().getDistance()), + () -> assertEquals(updatedSection.getId(), section.getId()) + ); + } +} From 7c020291cc5bee8eac17b56b0582c0dd90d5b3b3 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 12:27:53 +0900 Subject: [PATCH 26/41] =?UTF-8?q?test=20:=20SectionQueryService=20Integrat?= =?UTF-8?q?ion=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/service/RouteQueryService.java | 2 ++ .../subway/service/SectionCommandService.java | 2 ++ .../subway/service/SectionQueryService.java | 2 ++ .../service/SectionQueryServiceTest.java | 30 +++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 src/test/java/subway/service/SectionQueryServiceTest.java diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index bcc406240..9b9056a68 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,6 +1,7 @@ package subway.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import subway.domain.Money; import subway.domain.line.Line; import subway.domain.policy.ChargePolicyComposite; @@ -12,6 +13,7 @@ import java.util.List; @Service +@Transactional(readOnly = true) public class RouteQueryService { private final LineQueryService lineQueryService; diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/service/SectionCommandService.java index cd99de49c..d02d6ed79 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/service/SectionCommandService.java @@ -1,6 +1,7 @@ package subway.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import subway.dao.SectionDao; import subway.dao.SectionEntity; import subway.domain.section.Section; @@ -11,6 +12,7 @@ import java.util.List; @Service +@Transactional public class SectionCommandService { private final SectionDao sectionDao; diff --git a/src/main/java/subway/service/SectionQueryService.java b/src/main/java/subway/service/SectionQueryService.java index 239e79e94..d6f5068fe 100644 --- a/src/main/java/subway/service/SectionQueryService.java +++ b/src/main/java/subway/service/SectionQueryService.java @@ -1,6 +1,7 @@ package subway.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import subway.dao.SectionDao; import subway.dao.SectionEntity; import subway.domain.section.Section; @@ -11,6 +12,7 @@ import java.util.stream.Collectors; @Service +@Transactional(readOnly = true) public class SectionQueryService { private final SectionDao sectionDao; diff --git a/src/test/java/subway/service/SectionQueryServiceTest.java b/src/test/java/subway/service/SectionQueryServiceTest.java new file mode 100644 index 000000000..48eac7e8e --- /dev/null +++ b/src/test/java/subway/service/SectionQueryServiceTest.java @@ -0,0 +1,30 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.domain.section.Section; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SectionQueryServiceTest extends IntegrationTestHelper { + + @Autowired + private SectionQueryService sectionQueryService; + + @Test + @DisplayName("searchSectionsByLineId() : 해당 line에 속한 모든 섹션들을 조회할 수 있다.") + void test_searchSectionsByLineId() throws Exception { + //given + final long lineId = 1L; + + //when + final List
sections = sectionQueryService.searchSectionsByLineId(lineId); + + //then + assertEquals(3, sections.size()); + } +} From 868b6986834e1be2e559b6d833b89b17953f00e6 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 12:55:59 +0900 Subject: [PATCH 27/41] =?UTF-8?q?test=20:=20StationService=20Integration?= =?UTF-8?q?=20Test=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/service/StationServiceTest.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/test/java/subway/service/StationServiceTest.java diff --git a/src/test/java/subway/service/StationServiceTest.java b/src/test/java/subway/service/StationServiceTest.java new file mode 100644 index 000000000..d544af6df --- /dev/null +++ b/src/test/java/subway/service/StationServiceTest.java @@ -0,0 +1,102 @@ +package subway.service; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.dao.SectionDao; +import subway.dao.SectionEntity; +import subway.service.dto.StationDeleteRequest; +import subway.service.dto.StationRegisterRequest; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class StationServiceTest extends IntegrationTestHelper { + + @Autowired + private StationService stationService; + + @Autowired + private SectionDao sectionDao; + + @Test + @DisplayName("registerStation() : 역을 저장할 수 있다.") + void test_registerStation() throws Exception { + //given + final String currentStationName = "G"; + final String nextStationName = "K"; + final String lineName = "2호선"; + final int distance = 1; + + final StationRegisterRequest stationRegisterRequest = + new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); + + //when + stationService.registerStation(stationRegisterRequest); + + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(2L) + .stream() + .filter(it -> it.getId().equals(6L)) + .findAny() + .orElseThrow(); + + //then + assertAll( + () -> assertEquals("K", sectionEntity.getCurrentStationName()), + () -> assertEquals("H", sectionEntity.getNextStationName()), + () -> assertEquals(4, sectionEntity.getDistance()) + ); + } + + @Test + @DisplayName("deleteStation() : 해당 역을 삭제할 수 있다.") + void test_deleteStation() throws Exception { + //given + final String lineName = "1호선"; + final String stationName = "B"; + + final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName); + + //when + stationService.deleteStation(stationDeleteRequest); + + //then + + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(1L) + .stream() + .filter(it -> it.getId().equals(1L)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals("C", sectionEntity.getNextStationName()), + () -> assertEquals(3, sectionEntity.getDistance()) + ); + } + + @Test + @DisplayName("deleteStation() : 라인에 역이 하나만 존재하게 되면 라인이 같이 삭제될 수 있다.") + void test_deleteStation_deleteLine() throws Exception { + //given + final String lineName = "1호선"; + final String stationName1 = "B"; + final String stationName2 = "C"; + + final String stationName3 = "A"; + + final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName1); + stationService.deleteStation(new StationDeleteRequest(lineName, stationName1)); + stationService.deleteStation(new StationDeleteRequest(lineName, stationName2)); + + //when + stationService.deleteStation(new StationDeleteRequest(lineName, stationName3)); + + //then + final int size = sectionDao.findSectionsByLineId(1L).size(); + + assertEquals(0, size); + } +} From f3851498712d0ac6a2bc9329f5bf7c98817e11d7 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Mon, 22 May 2023 13:11:00 +0900 Subject: [PATCH 28/41] =?UTF-8?q?refactor=20:=20exception=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{global => }/exception/common/BusinessException.java | 2 +- .../exception/common/ExceptionHandlerController.java | 2 +- .../{global => }/exception/common/ExceptionResponse.java | 2 +- .../exception/line/CanNotDuplicatedLineNameException.java | 4 ++-- .../{global => }/exception/line/CanNotFoundLineException.java | 4 ++-- .../pricepolicy/CanNotDistanceEqualZeroException.java | 4 ++-- .../exception/section/CanNotDuplicatedSectionException.java | 4 ++-- src/main/java/subway/service/LineCommandService.java | 2 +- src/main/java/subway/service/LineQueryService.java | 2 +- src/main/java/subway/service/SectionCommandService.java | 2 +- src/test/java/subway/service/LineCommandServiceTest.java | 2 +- src/test/java/subway/service/SectionCommandServiceTest.java | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) rename src/main/java/subway/{global => }/exception/common/BusinessException.java (90%) rename src/main/java/subway/{global => }/exception/common/ExceptionHandlerController.java (98%) rename src/main/java/subway/{global => }/exception/common/ExceptionResponse.java (85%) rename src/main/java/subway/{global => }/exception/line/CanNotDuplicatedLineNameException.java (72%) rename src/main/java/subway/{global => }/exception/line/CanNotFoundLineException.java (70%) rename src/main/java/subway/{global => }/exception/pricepolicy/CanNotDistanceEqualZeroException.java (70%) rename src/main/java/subway/{global => }/exception/section/CanNotDuplicatedSectionException.java (71%) diff --git a/src/main/java/subway/global/exception/common/BusinessException.java b/src/main/java/subway/exception/common/BusinessException.java similarity index 90% rename from src/main/java/subway/global/exception/common/BusinessException.java rename to src/main/java/subway/exception/common/BusinessException.java index 8b4429dae..25cb232fd 100644 --- a/src/main/java/subway/global/exception/common/BusinessException.java +++ b/src/main/java/subway/exception/common/BusinessException.java @@ -1,4 +1,4 @@ -package subway.global.exception.common; +package subway.exception.common; import org.springframework.http.HttpStatus; diff --git a/src/main/java/subway/global/exception/common/ExceptionHandlerController.java b/src/main/java/subway/exception/common/ExceptionHandlerController.java similarity index 98% rename from src/main/java/subway/global/exception/common/ExceptionHandlerController.java rename to src/main/java/subway/exception/common/ExceptionHandlerController.java index 17b0dd462..593ef4538 100644 --- a/src/main/java/subway/global/exception/common/ExceptionHandlerController.java +++ b/src/main/java/subway/exception/common/ExceptionHandlerController.java @@ -1,4 +1,4 @@ -package subway.global.exception.common; +package subway.exception.common; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/subway/global/exception/common/ExceptionResponse.java b/src/main/java/subway/exception/common/ExceptionResponse.java similarity index 85% rename from src/main/java/subway/global/exception/common/ExceptionResponse.java rename to src/main/java/subway/exception/common/ExceptionResponse.java index 757edbd9e..421ce15fc 100644 --- a/src/main/java/subway/global/exception/common/ExceptionResponse.java +++ b/src/main/java/subway/exception/common/ExceptionResponse.java @@ -1,4 +1,4 @@ -package subway.global.exception.common; +package subway.exception.common; public class ExceptionResponse { diff --git a/src/main/java/subway/global/exception/line/CanNotDuplicatedLineNameException.java b/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java similarity index 72% rename from src/main/java/subway/global/exception/line/CanNotDuplicatedLineNameException.java rename to src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java index ab7de29e4..e784ad92f 100644 --- a/src/main/java/subway/global/exception/line/CanNotDuplicatedLineNameException.java +++ b/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java @@ -1,7 +1,7 @@ -package subway.global.exception.line; +package subway.exception.line; import org.springframework.http.HttpStatus; -import subway.global.exception.common.BusinessException; +import subway.exception.common.BusinessException; public class CanNotDuplicatedLineNameException extends BusinessException { diff --git a/src/main/java/subway/global/exception/line/CanNotFoundLineException.java b/src/main/java/subway/exception/line/CanNotFoundLineException.java similarity index 70% rename from src/main/java/subway/global/exception/line/CanNotFoundLineException.java rename to src/main/java/subway/exception/line/CanNotFoundLineException.java index 624eb04ad..f16c66c1b 100644 --- a/src/main/java/subway/global/exception/line/CanNotFoundLineException.java +++ b/src/main/java/subway/exception/line/CanNotFoundLineException.java @@ -1,7 +1,7 @@ -package subway.global.exception.line; +package subway.exception.line; import org.springframework.http.HttpStatus; -import subway.global.exception.common.BusinessException; +import subway.exception.common.BusinessException; public class CanNotFoundLineException extends BusinessException { diff --git a/src/main/java/subway/global/exception/pricepolicy/CanNotDistanceEqualZeroException.java b/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java similarity index 70% rename from src/main/java/subway/global/exception/pricepolicy/CanNotDistanceEqualZeroException.java rename to src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java index 4f735934a..68c89f2c7 100644 --- a/src/main/java/subway/global/exception/pricepolicy/CanNotDistanceEqualZeroException.java +++ b/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java @@ -1,7 +1,7 @@ -package subway.global.exception.pricepolicy; +package subway.exception.pricepolicy; import org.springframework.http.HttpStatus; -import subway.global.exception.common.BusinessException; +import subway.exception.common.BusinessException; public class CanNotDistanceEqualZeroException extends BusinessException { diff --git a/src/main/java/subway/global/exception/section/CanNotDuplicatedSectionException.java b/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java similarity index 71% rename from src/main/java/subway/global/exception/section/CanNotDuplicatedSectionException.java rename to src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java index 9a6475e77..57049ded7 100644 --- a/src/main/java/subway/global/exception/section/CanNotDuplicatedSectionException.java +++ b/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java @@ -1,7 +1,7 @@ -package subway.global.exception.section; +package subway.exception.section; import org.springframework.http.HttpStatus; -import subway.global.exception.common.BusinessException; +import subway.exception.common.BusinessException; public class CanNotDuplicatedSectionException extends BusinessException { diff --git a/src/main/java/subway/service/LineCommandService.java b/src/main/java/subway/service/LineCommandService.java index 264d7a065..29e6f39b7 100644 --- a/src/main/java/subway/service/LineCommandService.java +++ b/src/main/java/subway/service/LineCommandService.java @@ -4,7 +4,7 @@ import org.springframework.transaction.annotation.Transactional; import subway.dao.LineDao; import subway.dao.LineEntity; -import subway.global.exception.line.CanNotDuplicatedLineNameException; +import subway.exception.line.CanNotDuplicatedLineNameException; import subway.service.dto.RegisterLineRequest; @Service diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index 38cb5bb4d..d68ef9e78 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -5,7 +5,7 @@ import subway.dao.LineDao; import subway.dao.LineEntity; import subway.domain.line.Line; -import subway.global.exception.line.CanNotFoundLineException; +import subway.exception.line.CanNotFoundLineException; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/service/SectionCommandService.java index d02d6ed79..5aa15d543 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/service/SectionCommandService.java @@ -7,7 +7,7 @@ import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; -import subway.global.exception.section.CanNotDuplicatedSectionException; +import subway.exception.section.CanNotDuplicatedSectionException; import java.util.List; diff --git a/src/test/java/subway/service/LineCommandServiceTest.java b/src/test/java/subway/service/LineCommandServiceTest.java index f4dd0c0f0..f02734620 100644 --- a/src/test/java/subway/service/LineCommandServiceTest.java +++ b/src/test/java/subway/service/LineCommandServiceTest.java @@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import subway.dao.LineDao; import subway.dao.LineEntity; -import subway.global.exception.line.CanNotDuplicatedLineNameException; +import subway.exception.line.CanNotDuplicatedLineNameException; import subway.service.dto.RegisterLineRequest; import java.util.Optional; diff --git a/src/test/java/subway/service/SectionCommandServiceTest.java b/src/test/java/subway/service/SectionCommandServiceTest.java index cd6ae4eab..024705e9e 100644 --- a/src/test/java/subway/service/SectionCommandServiceTest.java +++ b/src/test/java/subway/service/SectionCommandServiceTest.java @@ -9,7 +9,7 @@ import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; -import subway.global.exception.section.CanNotDuplicatedSectionException; +import subway.exception.section.CanNotDuplicatedSectionException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; From 5f0a505465d62fbbfb4397f49793bab2a4e5f181 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Tue, 23 May 2023 23:40:15 +0900 Subject: [PATCH 29/41] =?UTF-8?q?refactor=20:=20java=20style=20google=20?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/SubwayApplication.java | 6 +- .../subway/controller/LineController.java | 77 +++--- .../subway/controller/RouteController.java | 25 +- .../subway/controller/StationController.java | 37 +-- src/main/java/subway/dao/LineDao.java | 85 +++--- src/main/java/subway/dao/LineEntity.java | 30 +-- src/main/java/subway/dao/SectionDao.java | 91 ++++--- src/main/java/subway/dao/SectionEntity.java | 102 +++---- src/main/java/subway/domain/Distance.java | 90 ++++--- src/main/java/subway/domain/Money.java | 90 ++++--- src/main/java/subway/domain/line/Line.java | 254 +++++++++--------- .../domain/policy/ChargePolicyComposite.java | 47 ++-- .../policy/discount/AgeDiscountPolicy.java | 57 ++-- .../domain/policy/discount/AgeGroup.java | 32 +-- .../policy/discount/DiscountCondition.java | 14 +- .../policy/discount/SubwayDiscountPolicy.java | 2 +- .../domain/policy/fare/DefaultFarePolicy.java | 62 ++--- .../domain/policy/fare/LineFarePolicy.java | 27 +- .../domain/policy/fare/SubwayFarePolicy.java | 2 +- .../java/subway/domain/route/EdgeSection.java | 64 ++--- .../domain/route/JgraphtRouteFinder.java | 124 ++++----- src/main/java/subway/domain/route/Route.java | 53 ++-- .../java/subway/domain/route/RouteFinder.java | 9 +- .../java/subway/domain/section/Section.java | 225 ++++++++-------- .../java/subway/domain/station/Station.java | 32 +-- .../java/subway/domain/station/Stations.java | 112 ++++---- .../exception/common/BusinessException.java | 16 +- .../common/ExceptionHandlerController.java | 82 +++--- .../exception/common/ExceptionResponse.java | 14 +- .../CanNotDuplicatedLineNameException.java | 6 +- .../line/CanNotFoundLineException.java | 6 +- .../CanNotDistanceEqualZeroException.java | 6 +- .../CanNotDuplicatedSectionException.java | 6 +- .../subway/service/LineCommandService.java | 64 ++--- .../java/subway/service/LineQueryService.java | 110 ++++---- .../subway/service/RouteQueryService.java | 82 +++--- .../subway/service/SectionCommandService.java | 114 ++++---- .../subway/service/SectionQueryService.java | 41 ++- .../java/subway/service/StationService.java | 169 ++++++------ .../service/dto/LeastCostRouteResponse.java | 54 ++-- .../java/subway/service/dto/LineResponse.java | 35 +-- .../service/dto/RegisterLineRequest.java | 70 ++--- .../subway/service/dto/SectionResponse.java | 35 +-- .../service/dto/ShortestRouteRequest.java | 35 +-- .../service/dto/ShortestRouteResponse.java | 34 +-- .../service/dto/StationDeleteRequest.java | 28 +- .../service/dto/StationRegisterRequest.java | 70 ++--- .../service/dto/StationRegisterResponse.java | 24 +- 48 files changed, 1429 insertions(+), 1421 deletions(-) diff --git a/src/main/java/subway/SubwayApplication.java b/src/main/java/subway/SubwayApplication.java index 5780e8fb1..88d0e32f7 100644 --- a/src/main/java/subway/SubwayApplication.java +++ b/src/main/java/subway/SubwayApplication.java @@ -6,8 +6,8 @@ @SpringBootApplication public class SubwayApplication { - public static void main(String[] args) { - SpringApplication.run(SubwayApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(SubwayApplication.class, args); + } } diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index 2a110476b..c100d692b 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -1,5 +1,7 @@ package subway.controller; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -15,54 +17,53 @@ import subway.service.dto.RegisterLineRequest; import subway.service.dto.SectionResponse; -import java.util.List; -import java.util.stream.Collectors; - @RestController public class LineController { - private final LineCommandService lineCommandService; - private final LineQueryService lineQueryService; + private final LineCommandService lineCommandService; + private final LineQueryService lineQueryService; - public LineController(final LineCommandService lineCommandService, final LineQueryService lineQueryService) { - this.lineCommandService = lineCommandService; - this.lineQueryService = lineQueryService; - } + public LineController(final LineCommandService lineCommandService, + final LineQueryService lineQueryService) { + this.lineCommandService = lineCommandService; + this.lineQueryService = lineQueryService; + } - @GetMapping("/lines") - @ResponseStatus(HttpStatus.OK) - public List showLine(@RequestParam(value = "lineName", required = false) String lineName) { - final List lines = lineQueryService.searchLines(lineName); + @GetMapping("/lines") + @ResponseStatus(HttpStatus.OK) + public List showLine( + @RequestParam(value = "lineName", required = false) String lineName) { + final List lines = lineQueryService.searchLines(lineName); - return lines.stream() - .map(line -> new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId())) - .collect(Collectors.toList()); - } + return lines.stream() + .map(line -> new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId())) + .collect(Collectors.toList()); + } - @GetMapping("/lines/{line-id}") - public LineResponse showLine(@PathVariable("line-id") Long lineId) { - final Line line = lineQueryService.searchByLineId(lineId); + @GetMapping("/lines/{line-id}") + public LineResponse showLine(@PathVariable("line-id") Long lineId) { + final Line line = lineQueryService.searchByLineId(lineId); - return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); - } + return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); + } - @PostMapping("/lines") - @ResponseStatus(HttpStatus.CREATED) - public LineResponse registerLine(@RequestBody RegisterLineRequest registerLineRequest) { - lineCommandService.registerLine(registerLineRequest); + @PostMapping("/lines") + @ResponseStatus(HttpStatus.CREATED) + public LineResponse registerLine(@RequestBody RegisterLineRequest registerLineRequest) { + lineCommandService.registerLine(registerLineRequest); - final Line line = lineQueryService.searchByLineName(registerLineRequest.getLineName()); + final Line line = lineQueryService.searchByLineName(registerLineRequest.getLineName()); - return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); - } + return new LineResponse(line.getName(), mapToSectionResponseFrom(line), line.getId()); + } - private List mapToSectionResponseFrom(final Line line) { - return line.getSections() - .stream() - .map(section -> new SectionResponse( - section.getStations().getCurrent().getName(), - section.getStations().getNext().getName(), - section.getStations().getDistance())) - .collect(Collectors.toList()); - } + private List mapToSectionResponseFrom(final Line line) { + return line.getSections() + .stream() + .map(section -> new SectionResponse( + section.getStations().getCurrent().getName(), + section.getStations().getNext().getName(), + section.getStations().getDistance())) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/subway/controller/RouteController.java b/src/main/java/subway/controller/RouteController.java index ef5cda497..48793ea71 100644 --- a/src/main/java/subway/controller/RouteController.java +++ b/src/main/java/subway/controller/RouteController.java @@ -10,18 +10,19 @@ @RestController public class RouteController { - private final RouteQueryService routeQueryService; + private final RouteQueryService routeQueryService; - public RouteController(final RouteQueryService routeQueryService) { - this.routeQueryService = routeQueryService; - } + public RouteController(final RouteQueryService routeQueryService) { + this.routeQueryService = routeQueryService; + } - @GetMapping("/route") - public ShortestRouteResponse showShortestRoute(@ModelAttribute ShortestRouteRequest shortestRouteRequest) { - return new ShortestRouteResponse( - routeQueryService.searchShortestRoute(shortestRouteRequest), - routeQueryService.searchLeastCost(shortestRouteRequest), - routeQueryService.searchShortestDistance(shortestRouteRequest) - ); - } + @GetMapping("/route") + public ShortestRouteResponse showShortestRoute( + @ModelAttribute ShortestRouteRequest shortestRouteRequest) { + return new ShortestRouteResponse( + routeQueryService.searchShortestRoute(shortestRouteRequest), + routeQueryService.searchLeastCost(shortestRouteRequest), + routeQueryService.searchShortestDistance(shortestRouteRequest) + ); + } } diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java index a7c76cb2d..94e6a4f82 100644 --- a/src/main/java/subway/controller/StationController.java +++ b/src/main/java/subway/controller/StationController.java @@ -14,26 +14,27 @@ @RestController public class StationController { - private final StationService stationService; + private final StationService stationService; - public StationController(final StationService stationService) { - this.stationService = stationService; - } + public StationController(final StationService stationService) { + this.stationService = stationService; + } - @PostMapping("/stations") - @ResponseStatus(HttpStatus.CREATED) - public StationRegisterResponse registerStation(@RequestBody StationRegisterRequest stationRegisterRequest) { - stationService.registerStation(stationRegisterRequest); + @PostMapping("/stations") + @ResponseStatus(HttpStatus.CREATED) + public StationRegisterResponse registerStation( + @RequestBody StationRegisterRequest stationRegisterRequest) { + stationService.registerStation(stationRegisterRequest); - return new StationRegisterResponse( - stationRegisterRequest.getLineName(), - stationRegisterRequest.getNextStationName() - ); - } + return new StationRegisterResponse( + stationRegisterRequest.getLineName(), + stationRegisterRequest.getNextStationName() + ); + } - @DeleteMapping("/stations") - @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteStation(@RequestBody StationDeleteRequest stationDeleteRequest) { - stationService.deleteStation(stationDeleteRequest); - } + @DeleteMapping("/stations") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteStation(@RequestBody StationDeleteRequest stationDeleteRequest) { + stationService.deleteStation(stationDeleteRequest); + } } diff --git a/src/main/java/subway/dao/LineDao.java b/src/main/java/subway/dao/LineDao.java index 8901803f5..7df3c8565 100644 --- a/src/main/java/subway/dao/LineDao.java +++ b/src/main/java/subway/dao/LineDao.java @@ -1,5 +1,7 @@ package subway.dao; +import java.util.List; +import java.util.Optional; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -7,62 +9,59 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; -import java.util.List; -import java.util.Optional; - @Repository public class LineDao { - private final JdbcTemplate jdbcTemplate; - private final SimpleJdbcInsert simpleJdbcInsert; - private final RowMapper rowMapper = (rs, rowNum) -> - new LineEntity( - rs.getLong("id"), - rs.getString("name") - ); + private final JdbcTemplate jdbcTemplate; + private final SimpleJdbcInsert simpleJdbcInsert; + private final RowMapper rowMapper = (rs, rowNum) -> + new LineEntity( + rs.getLong("id"), + rs.getString("name") + ); - public LineDao(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - this.simpleJdbcInsert = - new SimpleJdbcInsert(jdbcTemplate) - .withTableName("LINE") - .usingGeneratedKeyColumns("id"); - } + public LineDao(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + this.simpleJdbcInsert = + new SimpleJdbcInsert(jdbcTemplate) + .withTableName("LINE") + .usingGeneratedKeyColumns("id"); + } - public Optional findByLineName(final String lineName) { - final String sql = "SELECT * FROM LINE L WHERE L.name = ?"; + public Optional findByLineName(final String lineName) { + final String sql = "SELECT * FROM LINE L WHERE L.name = ?"; - try { - return Optional.ofNullable(jdbcTemplate.queryForObject(sql, rowMapper, lineName)); - } catch (EmptyResultDataAccessException exception) { - return Optional.empty(); - } + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(sql, rowMapper, lineName)); + } catch (EmptyResultDataAccessException exception) { + return Optional.empty(); } + } - public List findAll() { - final String sql = "SELECT * FROM LINE"; + public List findAll() { + final String sql = "SELECT * FROM LINE"; - return jdbcTemplate.query(sql, rowMapper); - } + return jdbcTemplate.query(sql, rowMapper); + } - public Optional findByLineId(final Long lineId) { - final String sql = "SELECT * FROM LINE L WHERE L.id = ?"; + public Optional findByLineId(final Long lineId) { + final String sql = "SELECT * FROM LINE L WHERE L.id = ?"; - try { - return Optional.ofNullable(jdbcTemplate.queryForObject(sql, rowMapper, lineId)); - } catch (EmptyResultDataAccessException exception) { - return Optional.empty(); - } + try { + return Optional.ofNullable(jdbcTemplate.queryForObject(sql, rowMapper, lineId)); + } catch (EmptyResultDataAccessException exception) { + return Optional.empty(); } + } - public void deleteById(final Long lineId) { - final String sql = "DELETE FROM LINE L WHERE L.id = ?"; + public void deleteById(final Long lineId) { + final String sql = "DELETE FROM LINE L WHERE L.id = ?"; - jdbcTemplate.update(sql, lineId); - } + jdbcTemplate.update(sql, lineId); + } - public Long save(final LineEntity lineEntity) { - return simpleJdbcInsert.executeAndReturnKey(new BeanPropertySqlParameterSource(lineEntity)) - .longValue(); - } + public Long save(final LineEntity lineEntity) { + return simpleJdbcInsert.executeAndReturnKey(new BeanPropertySqlParameterSource(lineEntity)) + .longValue(); + } } diff --git a/src/main/java/subway/dao/LineEntity.java b/src/main/java/subway/dao/LineEntity.java index 36e844135..43c3af7a1 100644 --- a/src/main/java/subway/dao/LineEntity.java +++ b/src/main/java/subway/dao/LineEntity.java @@ -2,23 +2,23 @@ public class LineEntity { - private Long id; - private String name; + private Long id; + private String name; - public LineEntity(final Long id, final String name) { - this.id = id; - this.name = name; - } + public LineEntity(final Long id, final String name) { + this.id = id; + this.name = name; + } - public LineEntity(final String name) { - this.name = name; - } + public LineEntity(final String name) { + this.name = name; + } - public Long getId() { - return id; - } + public Long getId() { + return id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } } diff --git a/src/main/java/subway/dao/SectionDao.java b/src/main/java/subway/dao/SectionDao.java index 9546593bc..7e70efabd 100644 --- a/src/main/java/subway/dao/SectionDao.java +++ b/src/main/java/subway/dao/SectionDao.java @@ -1,68 +1,67 @@ package subway.dao; +import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public class SectionDao { - private final JdbcTemplate jdbcTemplate; - private final SimpleJdbcInsert simpleJdbcInsert; - private final RowMapper rowMapper = (rs, rowNum) -> - new SectionEntity( - rs.getLong("id"), - rs.getString("current_station_name"), - rs.getString("next_station_name"), - rs.getInt("distance"), - rs.getLong("line_id") - ); + private final JdbcTemplate jdbcTemplate; + private final SimpleJdbcInsert simpleJdbcInsert; + private final RowMapper rowMapper = (rs, rowNum) -> + new SectionEntity( + rs.getLong("id"), + rs.getString("current_station_name"), + rs.getString("next_station_name"), + rs.getInt("distance"), + rs.getLong("line_id") + ); - public SectionDao(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - this.simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("SECTION") - .usingGeneratedKeyColumns("id"); - } + public SectionDao(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + this.simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("SECTION") + .usingGeneratedKeyColumns("id"); + } - public void save(final SectionEntity sectionEntity) { - simpleJdbcInsert.execute(new BeanPropertySqlParameterSource(sectionEntity)); - } + public void save(final SectionEntity sectionEntity) { + simpleJdbcInsert.execute(new BeanPropertySqlParameterSource(sectionEntity)); + } - public List findSectionsByLineId(final Long lineId) { - final String sql = "SELECT * FROM SECTION S WHERE S.line_id = ?"; + public List findSectionsByLineId(final Long lineId) { + final String sql = "SELECT * FROM SECTION S WHERE S.line_id = ?"; - return jdbcTemplate.query(sql, rowMapper, lineId); - } + return jdbcTemplate.query(sql, rowMapper, lineId); + } - public void deleteAll(final Long lineId) { - final String sql = "DELETE FROM SECTION S WHERE S.line_id = ?"; + public void deleteAll(final Long lineId) { + final String sql = "DELETE FROM SECTION S WHERE S.line_id = ?"; - jdbcTemplate.update(sql, lineId); - } + jdbcTemplate.update(sql, lineId); + } - public void update(final SectionEntity sectionEntity) { - final String sql = "UPDATE SECTION S SET S.current_station_name = ?, " - + "S.next_station_name = ?," - + "S.distance = ? " - + "WHERE S.id = ?"; + public void update(final SectionEntity sectionEntity) { + final String sql = "UPDATE SECTION S SET S.current_station_name = ?, " + + "S.next_station_name = ?," + + "S.distance = ? " + + "WHERE S.id = ?"; - jdbcTemplate.update( - sql, - sectionEntity.getCurrentStationName(), - sectionEntity.getNextStationName(), - sectionEntity.getDistance(), - sectionEntity.getId() - ); - } + jdbcTemplate.update( + sql, + sectionEntity.getCurrentStationName(), + sectionEntity.getNextStationName(), + sectionEntity.getDistance(), + sectionEntity.getId() + ); + } - public void deleteById(final Long sectionId) { - final String sql = "DELETE FROM SECTION S WHERE S.id = ?"; + public void deleteById(final Long sectionId) { + final String sql = "DELETE FROM SECTION S WHERE S.id = ?"; - jdbcTemplate.update(sql, sectionId); - } + jdbcTemplate.update(sql, sectionId); + } } diff --git a/src/main/java/subway/dao/SectionEntity.java b/src/main/java/subway/dao/SectionEntity.java index b5b9e1ab6..395827e0d 100644 --- a/src/main/java/subway/dao/SectionEntity.java +++ b/src/main/java/subway/dao/SectionEntity.java @@ -2,55 +2,55 @@ public class SectionEntity { - private Long id; - private String currentStationName; - private String nextStationName; - private int distance; - private Long lineId; - - public SectionEntity( - final Long id, final String currentStationName, - final String nextStationName, final int distance, - final Long lineId - ) { - this.id = id; - this.currentStationName = currentStationName; - this.nextStationName = nextStationName; - this.distance = distance; - this.lineId = lineId; - } - - public SectionEntity( - final String currentStationName, final String nextStationName, - final int distance, final Long lineId - ) { - this(null, currentStationName, nextStationName, distance, lineId); - } - - public SectionEntity( - final Long id, final String currentStationName, - final String nextStationName, final int distance - ) { - this(id, currentStationName, nextStationName, distance, null); - } - - public Long getId() { - return id; - } - - public String getCurrentStationName() { - return currentStationName; - } - - public String getNextStationName() { - return nextStationName; - } - - public int getDistance() { - return distance; - } - - public Long getLineId() { - return lineId; - } + private Long id; + private String currentStationName; + private String nextStationName; + private int distance; + private Long lineId; + + public SectionEntity( + final Long id, final String currentStationName, + final String nextStationName, final int distance, + final Long lineId + ) { + this.id = id; + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.distance = distance; + this.lineId = lineId; + } + + public SectionEntity( + final String currentStationName, final String nextStationName, + final int distance, final Long lineId + ) { + this(null, currentStationName, nextStationName, distance, lineId); + } + + public SectionEntity( + final Long id, final String currentStationName, + final String nextStationName, final int distance + ) { + this(id, currentStationName, nextStationName, distance, null); + } + + public Long getId() { + return id; + } + + public String getCurrentStationName() { + return currentStationName; + } + + public String getNextStationName() { + return nextStationName; + } + + public int getDistance() { + return distance; + } + + public Long getLineId() { + return lineId; + } } diff --git a/src/main/java/subway/domain/Distance.java b/src/main/java/subway/domain/Distance.java index 7f4d4cf6c..c68fac433 100644 --- a/src/main/java/subway/domain/Distance.java +++ b/src/main/java/subway/domain/Distance.java @@ -4,61 +4,65 @@ public class Distance { - public static final Distance DEFAULT_DISTANCE = new Distance(10); - public static final Distance LONG_DISTANCE = new Distance(50); - public static final Distance MID_DISTANCE = new Distance(40); + public static final Distance DEFAULT_DISTANCE = new Distance(10); + public static final Distance LONG_DISTANCE = new Distance(50); + public static final Distance MID_DISTANCE = new Distance(40); - private final int value; + private final int value; - public Distance(final int value) { - validateDistance(value); - this.value = value; - } + public Distance(final int value) { + validateDistance(value); + this.value = value; + } - private void validateDistance(final int distance) { - if (distance <= 0) { - throw new IllegalArgumentException("거리는 0이 될 수 없습니다."); - } + private void validateDistance(final int distance) { + if (distance <= 0) { + throw new IllegalArgumentException("거리는 0이 될 수 없습니다."); } + } - public boolean isShorterThan(final Distance other) { - return value <= other.value; - } + public boolean isShorterThan(final Distance other) { + return value <= other.value; + } - public Distance minus(final Distance other) { - return new Distance(value - other.value); - } + public Distance minus(final Distance other) { + return new Distance(value - other.value); + } - public Distance plus(final Distance other) { - return new Distance(value + other.value); - } + public Distance plus(final Distance other) { + return new Distance(value + other.value); + } - public Distance calculateDistanceUnit(final int rate) { - return new Distance(((value - 1) / rate) + 1); - } + public Distance calculateDistanceUnit(final int rate) { + return new Distance(((value - 1) / rate) + 1); + } - public boolean isDefaultDistance() { - return value <= DEFAULT_DISTANCE.value; - } + public boolean isDefaultDistance() { + return value <= DEFAULT_DISTANCE.value; + } - public boolean isLongDistance() { - return value > LONG_DISTANCE.value; - } + public boolean isLongDistance() { + return value > LONG_DISTANCE.value; + } - public int getValue() { - return value; - } + public int getValue() { + return value; + } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Distance distance = (Distance) o; - return value == distance.value; + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - - @Override - public int hashCode() { - return Objects.hash(value); + if (o == null || getClass() != o.getClass()) { + return false; } + final Distance distance = (Distance) o; + return value == distance.value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } } diff --git a/src/main/java/subway/domain/Money.java b/src/main/java/subway/domain/Money.java index 70cd6d99e..c106485e3 100644 --- a/src/main/java/subway/domain/Money.java +++ b/src/main/java/subway/domain/Money.java @@ -6,61 +6,65 @@ public class Money { - public static final Money ZERO = new Money(BigDecimal.ZERO); + public static final Money ZERO = new Money(BigDecimal.ZERO); - private final BigDecimal value; + private final BigDecimal value; - private Money(final BigDecimal value) { - validateNegative(value); - this.value = value; - } + private Money(final BigDecimal value) { + validateNegative(value); + this.value = value; + } - public Money(final double value) { - this(BigDecimal.valueOf(value)); - } + public Money(final double value) { + this(BigDecimal.valueOf(value)); + } - private void validateNegative(final BigDecimal value) { - if (value.doubleValue() < 0) { - throw new IllegalArgumentException("돈은 음수가 될 수 없습니다."); - } + private void validateNegative(final BigDecimal value) { + if (value.doubleValue() < 0) { + throw new IllegalArgumentException("돈은 음수가 될 수 없습니다."); } + } - public Money minus(final int value) { - return new Money(this.value.subtract(BigDecimal.valueOf(value))); - } + public Money minus(final int value) { + return new Money(this.value.subtract(BigDecimal.valueOf(value))); + } - public Money calculateDiscountedPrice(final int percentage) { - final int discountedPercentage = 100 - percentage; - return new Money(this.value.multiply(BigDecimal.valueOf(discountedPercentage)) - .divide(BigDecimal.valueOf(100), RoundingMode.HALF_DOWN)); - } + public Money calculateDiscountedPrice(final int percentage) { + final int discountedPercentage = 100 - percentage; + return new Money(this.value.multiply(BigDecimal.valueOf(discountedPercentage)) + .divide(BigDecimal.valueOf(100), RoundingMode.HALF_DOWN)); + } - public Money add(final BigDecimal value) { - return new Money(this.value.add(value)); - } + public Money add(final BigDecimal value) { + return new Money(this.value.add(value)); + } - public Money add(final Money money) { - return new Money(this.value.add(money.value)); - } + public Money add(final Money money) { + return new Money(this.value.add(money.value)); + } - public Money max(final Money other) { - return new Money(this.value.max(other.value)); - } + public Money max(final Money other) { + return new Money(this.value.max(other.value)); + } - public double getValue() { - return value.doubleValue(); - } + public double getValue() { + return value.doubleValue(); + } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Money money = (Money) o; - return Objects.equals(value, money.value); + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - - @Override - public int hashCode() { - return Objects.hash(value); + if (o == null || getClass() != o.getClass()) { + return false; } + final Money money = (Money) o; + return Objects.equals(value, money.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } } diff --git a/src/main/java/subway/domain/line/Line.java b/src/main/java/subway/domain/line/Line.java index 5ec89b657..be8b8b843 100644 --- a/src/main/java/subway/domain/line/Line.java +++ b/src/main/java/subway/domain/line/Line.java @@ -1,175 +1,173 @@ package subway.domain.line; -import subway.domain.section.Section; -import subway.domain.station.Station; - import java.util.ArrayList; import java.util.Collection; import java.util.List; +import subway.domain.section.Section; +import subway.domain.station.Station; public class Line { - private final Long id; - private final String name; - private Section starter; - - public Line( - final Long id, - final String name, - final Collection
sections - ) { - this.id = id; - this.name = name; - initialLine(sections); - } + private final Long id; + private final String name; + private Section starter; - private void initialLine(final Collection
sections) { - List
retrySection = new ArrayList<>(); + public Line( + final Long id, + final String name, + final Collection
sections + ) { + this.id = id; + this.name = name; + initialLine(sections); + } - for (final Section section : sections) { - addUnorderedSection(retrySection, section); - } + private void initialLine(final Collection
sections) { + List
retrySection = new ArrayList<>(); - retryUnorderedSection(retrySection); + for (final Section section : sections) { + addUnorderedSection(retrySection, section); } - private void addUnorderedSection( - final List
retrySection, - final Section section - ) { - try { - add(section); - } catch (IllegalArgumentException exception) { - retrySection.add(section); - } + retryUnorderedSection(retrySection); + } + + private void addUnorderedSection( + final List
retrySection, + final Section section + ) { + try { + add(section); + } catch (IllegalArgumentException exception) { + retrySection.add(section); } + } - private void retryUnorderedSection(final Collection
retrySection) { - for (final Section section : retrySection) { - add(section); - } + private void retryUnorderedSection(final Collection
retrySection) { + for (final Section section : retrySection) { + add(section); } + } - public void add(Section newSection) { - if (starter == null) { - starter = newSection; - return; - } + public void add(Section newSection) { + if (starter == null) { + starter = newSection; + return; + } - final Section targetSection = starter.findPreSectionOnAdd(newSection); - final Section sameStartSection = starter.findSameSectionOnAdd(newSection); + final Section targetSection = starter.findPreSectionOnAdd(newSection); + final Section sameStartSection = starter.findSameSectionOnAdd(newSection); - if (canExchangeStarter(targetSection)) { + if (canExchangeStarter(targetSection)) { - if (starter.isLinked(newSection)) { - exchangeStarterOnAdd(newSection); - return; - } + if (starter.isLinked(newSection)) { + exchangeStarterOnAdd(newSection); + return; + } - if (sameStartSection != null) { - newSection.updateNextSection(starter); - starter.updateSectionOnAdd(newSection); - starter = newSection; - return; - } + if (sameStartSection != null) { + newSection.updateNextSection(starter); + starter.updateSectionOnAdd(newSection); + starter = newSection; + return; + } + throw new IllegalArgumentException("해당 섹션은 현재 Line에 추가할 수 없습니다."); + } - throw new IllegalArgumentException("해당 섹션은 현재 Line에 추가할 수 없습니다."); - } + starter.addNext(newSection); + } - starter.addNext(newSection); - } + private boolean canExchangeStarter(final Section targetSection) { + return targetSection == null; + } - private boolean canExchangeStarter(final Section targetSection) { - return targetSection == null; - } + private void exchangeStarterOnAdd(final Section newSection) { + newSection.updateNextSection(starter); + starter = newSection; + } - private void exchangeStarterOnAdd(final Section newSection) { - newSection.updateNextSection(starter); - starter = newSection; - } + public void delete(final Station deletedStation) { + final Section target = starter.findPreSectionOnDelete(deletedStation); - public void delete(final Station deletedStation) { - final Section target = starter.findPreSectionOnDelete(deletedStation); - - if (canDeleteLine(target)) { - starter = null; - return; - } - - if (canExchangeStarter(target)) { - if (starter.isSameCurrentWith(deletedStation)) { - exchangeStarterOnDelete(); - return; - } - throw new IllegalArgumentException("삭제할 역이 없습니다."); - } - - if (canExchangeTail(target)) { - Section newTailSection = findPreSection(target); - newTailSection.disconnectNextSection(); - return; - } - - starter.delete(deletedStation); + if (canDeleteLine(target)) { + starter = null; + return; } - private boolean canDeleteLine(final Section target) { - return target == starter && target.getTo() == null; + if (canExchangeStarter(target)) { + if (starter.isSameCurrentWith(deletedStation)) { + exchangeStarterOnDelete(); + return; + } + throw new IllegalArgumentException("삭제할 역이 없습니다."); } - private void exchangeStarterOnDelete() { - final Section newStarter = starter.getTo(); - starter.disconnectNextSection(); - starter = newStarter; + if (canExchangeTail(target)) { + Section newTailSection = findPreSection(target); + newTailSection.disconnectNextSection(); + return; } - private boolean canExchangeTail(final Section target) { - return target.getTo() == null; - } + starter.delete(deletedStation); + } - private Section findPreSection(Section targetSection) { - Section current = starter; + private boolean canDeleteLine(final Section target) { + return target == starter && target.getTo() == null; + } - while (isNotTail(targetSection, current)) { - current = current.getTo(); - } - return current; - } + private void exchangeStarterOnDelete() { + final Section newStarter = starter.getTo(); + starter.disconnectNextSection(); + starter = newStarter; + } - private boolean isNotTail( - final Section targetSection, - final Section current - ) { - return current.getTo() != targetSection; - } + private boolean canExchangeTail(final Section target) { + return target.getTo() == null; + } - public boolean isDeleted() { - return starter == null; + private Section findPreSection(Section targetSection) { + Section current = starter; + + while (isNotTail(targetSection, current)) { + current = current.getTo(); } + return current; + } - public List
getSections() { - Section current = starter; + private boolean isNotTail( + final Section targetSection, + final Section current + ) { + return current.getTo() != targetSection; + } - List
sections = new ArrayList<>(); + public boolean isDeleted() { + return starter == null; + } - while (current != null) { - sections.add(current.cloneSection()); - current = current.getTo(); - } + public List
getSections() { + Section current = starter; - return sections; - } + List
sections = new ArrayList<>(); - public Long getId() { - return id; + while (current != null) { + sections.add(current.cloneSection()); + current = current.getTo(); } - public Section getStarter() { - return starter; - } + return sections; + } - public String getName() { - return name; - } + public Long getId() { + return id; + } + + public Section getStarter() { + return starter; + } + + public String getName() { + return name; + } } diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java index 517f58edb..aa290489b 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -1,5 +1,6 @@ package subway.domain.policy; +import java.util.List; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import subway.domain.Money; @@ -8,35 +9,33 @@ import subway.domain.policy.fare.SubwayFarePolicy; import subway.domain.route.Route; -import java.util.List; - @Primary @Component public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { - private final List farePolicies; - private final List discountPolicies; + private final List farePolicies; + private final List discountPolicies; - public ChargePolicyComposite( - final List farePolicies, - final List discountPolicies - ) { - this.farePolicies = farePolicies; - this.discountPolicies = discountPolicies; - } + public ChargePolicyComposite( + final List farePolicies, + final List discountPolicies + ) { + this.farePolicies = farePolicies; + this.discountPolicies = discountPolicies; + } - @Override - public Money calculate(final Route route) { - return farePolicies.stream() - .map(it -> it.calculate(route)) - .reduce(Money.ZERO, Money::add); - } + @Override + public Money calculate(final Route route) { + return farePolicies.stream() + .map(it -> it.calculate(route)) + .reduce(Money.ZERO, Money::add); + } - @Override - public Money discount(final DiscountCondition discountCondition, final Money price) { - return discountPolicies.stream() - .reduce(price, (money, subwayDiscountPolicy) -> - subwayDiscountPolicy.discount(discountCondition, money), - (money1, money2) -> money2); - } + @Override + public Money discount(final DiscountCondition discountCondition, final Money price) { + return discountPolicies.stream() + .reduce(price, (money, subwayDiscountPolicy) -> + subwayDiscountPolicy.discount(discountCondition, money), + (money1, money2) -> money2); + } } diff --git a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java index c6e0ce4ed..fca80d8e1 100644 --- a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java +++ b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java @@ -1,48 +1,47 @@ package subway.domain.policy.discount; -import org.springframework.stereotype.Component; -import subway.domain.Money; - import java.util.EnumMap; import java.util.Map; +import org.springframework.stereotype.Component; +import subway.domain.Money; @Component public class AgeDiscountPolicy implements SubwayDiscountPolicy { - private static final Map policyMap = new EnumMap<>(AgeGroup.class); + private static final Map policyMap = new EnumMap<>(AgeGroup.class); - static { - policyMap.put(AgeGroup.CHILD, new DiscountValue(350, 50)); - policyMap.put(AgeGroup.TEENAGER, new DiscountValue(350, 20)); - policyMap.put(AgeGroup.NONE, new DiscountValue(0, 0)); - } + static { + policyMap.put(AgeGroup.CHILD, new DiscountValue(350, 50)); + policyMap.put(AgeGroup.TEENAGER, new DiscountValue(350, 20)); + policyMap.put(AgeGroup.NONE, new DiscountValue(0, 0)); + } - @Override - public Money discount(final DiscountCondition discountCondition, final Money price) { + @Override + public Money discount(final DiscountCondition discountCondition, final Money price) { - final AgeGroup ageGroup = AgeGroup.findAgeGroup(discountCondition.getAge()); - final DiscountValue discountValue = policyMap.get(ageGroup); + final AgeGroup ageGroup = AgeGroup.findAgeGroup(discountCondition.getAge()); + final DiscountValue discountValue = policyMap.get(ageGroup); - return price.minus(discountValue.getDiscountPrice()) - .calculateDiscountedPrice(discountValue.getPercent()); - } + return price.minus(discountValue.getDiscountPrice()) + .calculateDiscountedPrice(discountValue.getPercent()); + } - private static class DiscountValue { + private static class DiscountValue { - private final int discountPrice; - private final int percent; + private final int discountPrice; + private final int percent; - public DiscountValue(final int discountPrice, final int percent) { - this.discountPrice = discountPrice; - this.percent = percent; - } + public DiscountValue(final int discountPrice, final int percent) { + this.discountPrice = discountPrice; + this.percent = percent; + } - public int getDiscountPrice() { - return discountPrice; - } + public int getDiscountPrice() { + return discountPrice; + } - public int getPercent() { - return percent; - } + public int getPercent() { + return percent; } + } } diff --git a/src/main/java/subway/domain/policy/discount/AgeGroup.java b/src/main/java/subway/domain/policy/discount/AgeGroup.java index db10ccd66..ba85ee2e6 100644 --- a/src/main/java/subway/domain/policy/discount/AgeGroup.java +++ b/src/main/java/subway/domain/policy/discount/AgeGroup.java @@ -5,23 +5,23 @@ public enum AgeGroup { - TEENAGER(13, 19), - CHILD(6, 13), - NONE(0, 0); + TEENAGER(13, 19), + CHILD(6, 13), + NONE(0, 0); - private final int ageLowLimit; - private final int ageHighLimit; + private final int ageLowLimit; + private final int ageHighLimit; - AgeGroup(final int ageLowLimit, final int ageHighLimit) { - this.ageLowLimit = ageLowLimit; - this.ageHighLimit = ageHighLimit; - } + AgeGroup(final int ageLowLimit, final int ageHighLimit) { + this.ageLowLimit = ageLowLimit; + this.ageHighLimit = ageHighLimit; + } - public static AgeGroup findAgeGroup(final Integer target) { - return Arrays.stream(values()) - .filter(age -> Objects.nonNull(target)) - .filter(age -> target >= age.ageLowLimit && target < age.ageHighLimit) - .findAny() - .orElse(NONE); - } + public static AgeGroup findAgeGroup(final Integer target) { + return Arrays.stream(values()) + .filter(age -> Objects.nonNull(target)) + .filter(age -> target >= age.ageLowLimit && target < age.ageHighLimit) + .findAny() + .orElse(NONE); + } } diff --git a/src/main/java/subway/domain/policy/discount/DiscountCondition.java b/src/main/java/subway/domain/policy/discount/DiscountCondition.java index b126ac336..7226b7386 100644 --- a/src/main/java/subway/domain/policy/discount/DiscountCondition.java +++ b/src/main/java/subway/domain/policy/discount/DiscountCondition.java @@ -2,13 +2,13 @@ public class DiscountCondition { - private final Integer age; + private final Integer age; - public DiscountCondition(final Integer age) { - this.age = age; - } + public DiscountCondition(final Integer age) { + this.age = age; + } - public Integer getAge() { - return age; - } + public Integer getAge() { + return age; + } } diff --git a/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java b/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java index 9df7bea2d..db76f8709 100644 --- a/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java +++ b/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java @@ -4,5 +4,5 @@ public interface SubwayDiscountPolicy { - Money discount(final DiscountCondition discountCondition, final Money price); + Money discount(final DiscountCondition discountCondition, final Money price); } diff --git a/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java b/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java index 38da25fef..2b4d6b2d9 100644 --- a/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java @@ -1,49 +1,49 @@ package subway.domain.policy.fare; +import static subway.domain.Distance.DEFAULT_DISTANCE; +import static subway.domain.Distance.MID_DISTANCE; + +import java.math.BigDecimal; import org.springframework.stereotype.Component; import subway.domain.Distance; import subway.domain.Money; import subway.domain.route.Route; -import java.math.BigDecimal; - -import static subway.domain.Distance.DEFAULT_DISTANCE; -import static subway.domain.Distance.MID_DISTANCE; - @Component public class DefaultFarePolicy implements SubwayFarePolicy { - private static final Money DEFAULT_PRICE = new Money(1250); - private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); - private static final int MID_DISTANCE_RATE = 5; - private static final int LONG_DISTANCE_RATE = 8; - - @Override - public Money calculate(final Route route) { - final Distance distanceValue = route.findShortestRouteDistance(); + private static final Money DEFAULT_PRICE = new Money(1250); + private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); + private static final int MID_DISTANCE_RATE = 5; + private static final int LONG_DISTANCE_RATE = 8; - if (distanceValue.isDefaultDistance()) { - return DEFAULT_PRICE; - } + @Override + public Money calculate(final Route route) { + final Distance distanceValue = route.findShortestRouteDistance(); - if (distanceValue.isLongDistance()) { - return DEFAULT_PRICE.add(calculateMidDistance(MID_DISTANCE)) - .add(calculateLongDistance(distanceValue.minus(MID_DISTANCE) - .minus(DEFAULT_DISTANCE))); - } - - return DEFAULT_PRICE.add(calculateMidDistance(distanceValue.minus(DEFAULT_DISTANCE))); + if (distanceValue.isDefaultDistance()) { + return DEFAULT_PRICE; } - private BigDecimal calculateMidDistance(final Distance distance) { - return calculatePriceBracket(distance, MID_DISTANCE_RATE); + if (distanceValue.isLongDistance()) { + return DEFAULT_PRICE.add(calculateMidDistance(MID_DISTANCE)) + .add(calculateLongDistance(distanceValue.minus(MID_DISTANCE) + .minus(DEFAULT_DISTANCE))); } - private BigDecimal calculateLongDistance(final Distance distance) { - return calculatePriceBracket(distance, LONG_DISTANCE_RATE); - } + return DEFAULT_PRICE.add(calculateMidDistance(distanceValue.minus(DEFAULT_DISTANCE))); + } - private BigDecimal calculatePriceBracket(final Distance distance, final int rate) { - return BigDecimal.valueOf(distance.calculateDistanceUnit(rate).getValue()).multiply(ADDITIONAL_FEE); - } + private BigDecimal calculateMidDistance(final Distance distance) { + return calculatePriceBracket(distance, MID_DISTANCE_RATE); + } + + private BigDecimal calculateLongDistance(final Distance distance) { + return calculatePriceBracket(distance, LONG_DISTANCE_RATE); + } + + private BigDecimal calculatePriceBracket(final Distance distance, final int rate) { + return BigDecimal.valueOf(distance.calculateDistanceUnit(rate).getValue()) + .multiply(ADDITIONAL_FEE); + } } diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java index ef2719813..6f377411f 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -1,28 +1,27 @@ package subway.domain.policy.fare; +import java.util.List; +import java.util.Map; import org.springframework.stereotype.Component; import subway.domain.Money; import subway.domain.route.EdgeSection; import subway.domain.route.Route; -import java.util.List; -import java.util.Map; - @Component public class LineFarePolicy implements SubwayFarePolicy { - private static final Map priceMap - = Map.of("1호선", 500, - "2호선", 1000); + private static final Map priceMap + = Map.of("1호선", 500, + "2호선", 1000); - @Override - public Money calculate(final Route route) { + @Override + public Money calculate(final Route route) { - final List shortestRouteSections = route.findShortestRouteSections(); + final List shortestRouteSections = route.findShortestRouteSections(); - return shortestRouteSections.stream() - .reduce(Money.ZERO, (money, edgeSection) -> - new Money(priceMap.getOrDefault(edgeSection.getLineName(), 0)), - (Money::max)); - } + return shortestRouteSections.stream() + .reduce(Money.ZERO, (money, edgeSection) -> + new Money(priceMap.getOrDefault(edgeSection.getLineName(), 0)), + (Money::max)); + } } diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java index 36e4a080a..50c579fc3 100644 --- a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java @@ -5,5 +5,5 @@ public interface SubwayFarePolicy { - Money calculate(final Route route); + Money calculate(final Route route); } diff --git a/src/main/java/subway/domain/route/EdgeSection.java b/src/main/java/subway/domain/route/EdgeSection.java index 70204758b..4e2db4417 100644 --- a/src/main/java/subway/domain/route/EdgeSection.java +++ b/src/main/java/subway/domain/route/EdgeSection.java @@ -4,36 +4,36 @@ public class EdgeSection extends DefaultWeightedEdge { - private final String startStation; - private final String endStation; - private final int distance; - private final String lineName; - - public EdgeSection( - final String startStation, - final String endStation, - final int distance, - final String lineName - ) { - this.startStation = startStation; - this.endStation = endStation; - this.distance = distance; - this.lineName = lineName; - } - - public String getStartStation() { - return startStation; - } - - public String getEndStation() { - return endStation; - } - - public String getLineName() { - return lineName; - } - - public int getDistance() { - return distance; - } + private final String startStation; + private final String endStation; + private final int distance; + private final String lineName; + + public EdgeSection( + final String startStation, + final String endStation, + final int distance, + final String lineName + ) { + this.startStation = startStation; + this.endStation = endStation; + this.distance = distance; + this.lineName = lineName; + } + + public String getStartStation() { + return startStation; + } + + public String getEndStation() { + return endStation; + } + + public String getLineName() { + return lineName; + } + + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java index d0cd8f926..0d1389334 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -1,5 +1,6 @@ package subway.domain.route; +import java.util.List; import org.jgrapht.Graph; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.WeightedMultigraph; @@ -8,78 +9,77 @@ import subway.domain.section.Section; import subway.domain.station.Stations; -import java.util.List; - public class JgraphtRouteFinder implements RouteFinder { - private final DijkstraShortestPath dijkstraGraph; - - public JgraphtRouteFinder(final List lines) { - Graph graph - = new WeightedMultigraph<>(EdgeSection.class); + private final DijkstraShortestPath dijkstraGraph; - for (final Line line : lines) { - final List
sections = line.getSections(); - makeGraphFromSections(graph, line); - } + public JgraphtRouteFinder(final List lines) { + Graph graph + = new WeightedMultigraph<>(EdgeSection.class); - dijkstraGraph = new DijkstraShortestPath<>(graph); + for (final Line line : lines) { + final List
sections = line.getSections(); + makeGraphFromSections(graph, line); } - private void makeGraphFromSections( - final Graph graph, - final Line line - ) { + dijkstraGraph = new DijkstraShortestPath<>(graph); + } - final List
sections = line.getSections(); + private void makeGraphFromSections( + final Graph graph, + final Line line + ) { - for (final Section section : sections) { - final Stations stations = section.getStations(); + final List
sections = line.getSections(); - final String startStation = stations.getCurrent().getName(); - final String endStation = stations.getNext().getName(); - final int distance = stations.getDistance(); - - addVertex(graph, startStation, endStation); - addEdge(graph, startStation, endStation, distance, line.getName()); - } - } - - private void addVertex( - final Graph graph, - final String startStation, - final String endStation - ) { - graph.addVertex(startStation); - graph.addVertex(endStation); - } + for (final Section section : sections) { + final Stations stations = section.getStations(); - private void addEdge( - final Graph graph, final String startStation, - final String endStation, final int distance, final String lineName - ) { - final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); - final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); - - graph.addEdge(startStation, endStation, start); - graph.addEdge(endStation, startStation, end); - - graph.setEdgeWeight(start, distance); - graph.setEdgeWeight(end, distance); - } - - @Override - public List findShortestRoute(final String startStation, final String endStation) { - return dijkstraGraph.getPath(startStation, endStation).getVertexList(); - } - - @Override - public Distance findShortestRouteDistance(final String startStation, final String endStation) { - return new Distance((int) dijkstraGraph.getPathWeight(startStation, endStation)); - } + final String startStation = stations.getCurrent().getName(); + final String endStation = stations.getNext().getName(); + final int distance = stations.getDistance(); - @Override - public List findShortestRouteSections(final String startStation, final String endStation) { - return dijkstraGraph.getPath(startStation, endStation).getEdgeList(); + addVertex(graph, startStation, endStation); + addEdge(graph, startStation, endStation, distance, line.getName()); } + } + + private void addVertex( + final Graph graph, + final String startStation, + final String endStation + ) { + graph.addVertex(startStation); + graph.addVertex(endStation); + } + + private void addEdge( + final Graph graph, final String startStation, + final String endStation, final int distance, final String lineName + ) { + final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); + final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); + + graph.addEdge(startStation, endStation, start); + graph.addEdge(endStation, startStation, end); + + graph.setEdgeWeight(start, distance); + graph.setEdgeWeight(end, distance); + } + + @Override + public List findShortestRoute(final String startStation, final String endStation) { + return dijkstraGraph.getPath(startStation, endStation).getVertexList(); + } + + @Override + public Distance findShortestRouteDistance(final String startStation, final String endStation) { + return new Distance((int) dijkstraGraph.getPathWeight(startStation, endStation)); + } + + @Override + public List findShortestRouteSections(final String startStation, + final String endStation) { + return dijkstraGraph.getPath(startStation, endStation).getEdgeList(); + } } diff --git a/src/main/java/subway/domain/route/Route.java b/src/main/java/subway/domain/route/Route.java index 8ec27d44a..12470e0fc 100644 --- a/src/main/java/subway/domain/route/Route.java +++ b/src/main/java/subway/domain/route/Route.java @@ -1,36 +1,35 @@ package subway.domain.route; +import java.util.List; import subway.domain.Distance; import subway.domain.line.Line; import subway.domain.station.Station; -import java.util.List; - public class Route { - private final RouteFinder routeFinder; - private final Station from; - private final Station to; - - public Route( - final List lines, - final Station from, - final Station to - ) { - this.routeFinder = new JgraphtRouteFinder(lines); - this.from = from; - this.to = to; - } - - public List findShortestRoute() { - return routeFinder.findShortestRoute(from.getName(), to.getName()); - } - - public Distance findShortestRouteDistance() { - return routeFinder.findShortestRouteDistance(from.getName(), to.getName()); - } - - public List findShortestRouteSections() { - return routeFinder.findShortestRouteSections(from.getName(), to.getName()); - } + private final RouteFinder routeFinder; + private final Station from; + private final Station to; + + public Route( + final List lines, + final Station from, + final Station to + ) { + this.routeFinder = new JgraphtRouteFinder(lines); + this.from = from; + this.to = to; + } + + public List findShortestRoute() { + return routeFinder.findShortestRoute(from.getName(), to.getName()); + } + + public Distance findShortestRouteDistance() { + return routeFinder.findShortestRouteDistance(from.getName(), to.getName()); + } + + public List findShortestRouteSections() { + return routeFinder.findShortestRouteSections(from.getName(), to.getName()); + } } diff --git a/src/main/java/subway/domain/route/RouteFinder.java b/src/main/java/subway/domain/route/RouteFinder.java index 21df2961c..b90f1be03 100644 --- a/src/main/java/subway/domain/route/RouteFinder.java +++ b/src/main/java/subway/domain/route/RouteFinder.java @@ -1,14 +1,13 @@ package subway.domain.route; -import subway.domain.Distance; - import java.util.List; +import subway.domain.Distance; public interface RouteFinder { - List findShortestRoute(final String startStation, final String endStation); + List findShortestRoute(final String startStation, final String endStation); - Distance findShortestRouteDistance(final String startStation, final String endStation); + Distance findShortestRouteDistance(final String startStation, final String endStation); - List findShortestRouteSections(final String startStation, final String endStation); + List findShortestRouteSections(final String startStation, final String endStation); } diff --git a/src/main/java/subway/domain/section/Section.java b/src/main/java/subway/domain/section/Section.java index 908e48658..ab1130b68 100644 --- a/src/main/java/subway/domain/section/Section.java +++ b/src/main/java/subway/domain/section/Section.java @@ -1,160 +1,163 @@ package subway.domain.section; +import java.util.Objects; import subway.domain.station.Station; import subway.domain.station.Stations; -import java.util.Objects; - public class Section { - private final Long id; - private final Stations stations; - private Section to; + private final Long id; + private final Stations stations; + private Section to; - public Section(final Long id, final Stations stations) { - this.id = id; - this.stations = stations; - to = null; - } + public Section(final Long id, final Stations stations) { + this.id = id; + this.stations = stations; + to = null; + } + + public Section(final Stations stations) { + this(null, stations); + } + + public Section findPreSectionOnAdd(final Section newSection) { + Section current = this; - public Section(final Stations stations) { - this(null, stations); + while (current != null) { + if (current.stations.isLinked(newSection.stations)) { + return current; + } + current = current.to; } - public Section findPreSectionOnAdd(final Section newSection) { - Section current = this; + return null; + } - while (current != null) { - if (current.stations.isLinked(newSection.stations)) { - return current; - } - current = current.to; - } + public Section findSameSectionOnAdd(final Section newSection) { + Section current = this; - return null; + while (current != null) { + if (current.stations.isSameCurrent(newSection.stations.getCurrent())) { + return current; + } + current = current.to; } - public Section findSameSectionOnAdd(final Section newSection) { - Section current = this; + return null; + } - while (current != null) { - if (current.stations.isSameCurrent(newSection.stations.getCurrent())) { - return current; - } - current = current.to; - } + public void addNext(final Section newSection) { + Section current = findPreSectionOnAdd(newSection); - return null; + if (isTail(current)) { + current.to = newSection; + return; } - public void addNext(final Section newSection) { - Section current = findPreSectionOnAdd(newSection); + if (current.to.stations.isDistanceShorterThan(newSection.stations)) { + throw new IllegalArgumentException("새로운 구간이 길이가 기존 구간의 길이보다 깁니다."); + } - if (isTail(current)) { - current.to = newSection; - return; - } + addIntermediate(newSection, current); + } - if (current.to.stations.isDistanceShorterThan(newSection.stations)) { - throw new IllegalArgumentException("새로운 구간이 길이가 기존 구간의 길이보다 깁니다."); - } + private boolean isTail(final Section current) { + return current.to == null; + } - addIntermediate(newSection, current); - } + private void addIntermediate(final Section newSection, final Section current) { + newSection.to = current.to; + current.to = newSection; - private boolean isTail(final Section current) { - return current.to == null; - } + newSection.to.stations.updateStationOnAdd(newSection.stations); + } - private void addIntermediate(final Section newSection, final Section current) { - newSection.to = current.to; - current.to = newSection; + public void updateSectionOnAdd(final Section newSection) { + stations.updateStationOnAdd(newSection.stations); + } - newSection.to.stations.updateStationOnAdd(newSection.stations); - } + public boolean isLinked(final Section other) { + return other.stations.isLinked(this.stations); + } - public void updateSectionOnAdd(final Section newSection) { - stations.updateStationOnAdd(newSection.stations); - } + public void delete(final Station deletedStation) { + final Section current = findPreSectionOnDelete(deletedStation); - public boolean isLinked(final Section other) { - return other.stations.isLinked(this.stations); + if (current == null) { + throw new IllegalArgumentException("해당 Section에는 삭제할 역이 존재하지 않습니다."); } - public void delete(final Station deletedStation) { - final Section current = findPreSectionOnDelete(deletedStation); + final Section deletedSection = current.to; - if (current == null) { - throw new IllegalArgumentException("해당 Section에는 삭제할 역이 존재하지 않습니다."); - } + current.stations.updateStationOnDelete(deletedSection.stations); - final Section deletedSection = current.to; + updateSectionOnDelete(current, deletedSection); + } - current.stations.updateStationOnDelete(deletedSection.stations); + private void updateSectionOnDelete(final Section current, final Section deletedSection) { + current.to = deletedSection.to; + deletedSection.to = null; + } - updateSectionOnDelete(current, deletedSection); - } + public Section findPreSectionOnDelete(final Station station) { + Section current = this; - private void updateSectionOnDelete(final Section current, final Section deletedSection) { - current.to = deletedSection.to; - deletedSection.to = null; + while (current != null) { + if (current.stations.isSameNext(station)) { + return current; + } + current = current.to; } - public Section findPreSectionOnDelete(final Station station) { - Section current = this; + return null; + } - while (current != null) { - if (current.stations.isSameNext(station)) { - return current; - } - current = current.to; - } + public boolean isSameCurrentWith(final Station station) { + return stations.isSameCurrent(station); + } - return null; - } + public boolean isSame(final Section section) { + return stations.isSame(section.stations); + } - public boolean isSameCurrentWith(final Station station) { - return stations.isSameCurrent(station); - } + public void disconnectNextSection() { + updateNextSection(null); + } - public boolean isSame(final Section section) { - return stations.isSame(section.stations); - } + public void updateNextSection(final Section section) { + to = section; + } - public void disconnectNextSection() { - updateNextSection(null); - } + public Section cloneSection() { + return new Section(id, stations.cloneStations()); + } - public void updateNextSection(final Section section) { - to = section; - } + public Long getId() { + return id; + } - public Section cloneSection() { - return new Section(id, stations.cloneStations()); - } + public Stations getStations() { + return stations; + } - public Long getId() { - return id; - } + public Section getTo() { + return to; + } - public Stations getStations() { - return stations; + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - - public Section getTo() { - return to; + if (o == null || getClass() != o.getClass()) { + return false; } + final Section section = (Section) o; + return Objects.equals(id, section.id); + } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Section section = (Section) o; - return Objects.equals(id, section.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } + @Override + public int hashCode() { + return Objects.hash(id); + } } diff --git a/src/main/java/subway/domain/station/Station.java b/src/main/java/subway/domain/station/Station.java index 19832025a..ed414b57e 100644 --- a/src/main/java/subway/domain/station/Station.java +++ b/src/main/java/subway/domain/station/Station.java @@ -2,25 +2,25 @@ public class Station { - private String name; + private String name; - public Station(final String name) { - this.name = name; - } + public Station(final String name) { + this.name = name; + } - public boolean isSame(final Station other) { - return name.equals(other.name); - } + public boolean isSame(final Station other) { + return name.equals(other.name); + } - public void updateStationName(final Station station) { - name = station.name; - } + public void updateStationName(final Station station) { + name = station.name; + } - public Station cloneStation() { - return new Station(name); - } + public Station cloneStation() { + return new Station(name); + } - public String getName() { - return name; - } + public String getName() { + return name; + } } diff --git a/src/main/java/subway/domain/station/Stations.java b/src/main/java/subway/domain/station/Stations.java index 9a2d98967..9d18a72c6 100644 --- a/src/main/java/subway/domain/station/Stations.java +++ b/src/main/java/subway/domain/station/Stations.java @@ -4,60 +4,60 @@ public class Stations { - private final Station current; - private final Station next; - private Distance distance; - - public Stations(final Station current, final Station next, final int distance) { - this.current = current; - this.next = next; - this.distance = new Distance(distance); - } - - public boolean isLinked(final Stations other) { - return next.isSame(other.current); - } - - public boolean isSameCurrent(final Station other) { - return current.isSame(other); - } - - public boolean isSameNext(final Station other) { - return next.isSame(other); - } - - public boolean isDistanceShorterThan(final Stations other) { - return distance.isShorterThan(other.distance); - } - - public boolean isSame(final Stations stations) { - return current.isSame(stations.current) - && next.isSame(stations.next); - } - - public void updateStationOnAdd(final Stations newStations) { - current.updateStationName(newStations.next); - distance = distance.minus(newStations.distance); - } - - public void updateStationOnDelete(final Stations deleteStations) { - next.updateStationName(deleteStations.next); - distance = distance.plus(deleteStations.distance); - } - - public Stations cloneStations() { - return new Stations(current.cloneStation(), next.cloneStation(), distance.getValue()); - } - - public int getDistance() { - return distance.getValue(); - } - - public Station getCurrent() { - return current; - } - - public Station getNext() { - return next; - } + private final Station current; + private final Station next; + private Distance distance; + + public Stations(final Station current, final Station next, final int distance) { + this.current = current; + this.next = next; + this.distance = new Distance(distance); + } + + public boolean isLinked(final Stations other) { + return next.isSame(other.current); + } + + public boolean isSameCurrent(final Station other) { + return current.isSame(other); + } + + public boolean isSameNext(final Station other) { + return next.isSame(other); + } + + public boolean isDistanceShorterThan(final Stations other) { + return distance.isShorterThan(other.distance); + } + + public boolean isSame(final Stations stations) { + return current.isSame(stations.current) + && next.isSame(stations.next); + } + + public void updateStationOnAdd(final Stations newStations) { + current.updateStationName(newStations.next); + distance = distance.minus(newStations.distance); + } + + public void updateStationOnDelete(final Stations deleteStations) { + next.updateStationName(deleteStations.next); + distance = distance.plus(deleteStations.distance); + } + + public Stations cloneStations() { + return new Stations(current.cloneStation(), next.cloneStation(), distance.getValue()); + } + + public int getDistance() { + return distance.getValue(); + } + + public Station getCurrent() { + return current; + } + + public Station getNext() { + return next; + } } diff --git a/src/main/java/subway/exception/common/BusinessException.java b/src/main/java/subway/exception/common/BusinessException.java index 25cb232fd..f3caa228f 100644 --- a/src/main/java/subway/exception/common/BusinessException.java +++ b/src/main/java/subway/exception/common/BusinessException.java @@ -4,14 +4,14 @@ public class BusinessException extends RuntimeException { - private final HttpStatus httpStatus; + private final HttpStatus httpStatus; - public BusinessException(final String message, final HttpStatus httpStatus) { - super(message); - this.httpStatus = httpStatus; - } + public BusinessException(final String message, final HttpStatus httpStatus) { + super(message); + this.httpStatus = httpStatus; + } - public HttpStatus getHttpStatus() { - return httpStatus; - } + public HttpStatus getHttpStatus() { + return httpStatus; + } } diff --git a/src/main/java/subway/exception/common/ExceptionHandlerController.java b/src/main/java/subway/exception/common/ExceptionHandlerController.java index 593ef4538..a2f9a8446 100644 --- a/src/main/java/subway/exception/common/ExceptionHandlerController.java +++ b/src/main/java/subway/exception/common/ExceptionHandlerController.java @@ -11,43 +11,47 @@ @RestControllerAdvice public class ExceptionHandlerController { - private final Logger log = LoggerFactory.getLogger(getClass()); - - @ExceptionHandler(IllegalArgumentException.class) - public ResponseEntity handleDomainException(IllegalArgumentException exception) { - errorLogging(exception); - - return ResponseEntity.badRequest() - .body(new ExceptionResponse(exception.getMessage())); - } - - @ExceptionHandler(BusinessException.class) - public ResponseEntity handleBusinessException(BusinessException exception) { - errorLogging(exception); - - return new ResponseEntity<>(new ExceptionResponse(exception.getMessage()), exception.getHttpStatus()); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity handleUnexpectedException(Exception exception) { - errorLogging(exception); - - return ResponseEntity.internalServerError() - .body(new ExceptionResponse(String.format("전화 주세요 : %s", exception.getMessage()))); - } - - @ExceptionHandler(DataAccessResourceFailureException.class) - public ResponseEntity handleDatabaseException(DataAccessResourceFailureException exception) { - errorLogging(exception); - - return new ResponseEntity<>(new ExceptionResponse(exception.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR); - } - - private void errorLogging(Exception exception) { - log.info( - "클래스 이름 = {} 메시지 = {}", - exception.getClass().getSimpleName(), - exception.getMessage() - ); - } + private final Logger log = LoggerFactory.getLogger(getClass()); + + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity handleDomainException( + IllegalArgumentException exception) { + errorLogging(exception); + + return ResponseEntity.badRequest() + .body(new ExceptionResponse(exception.getMessage())); + } + + @ExceptionHandler(BusinessException.class) + public ResponseEntity handleBusinessException(BusinessException exception) { + errorLogging(exception); + + return new ResponseEntity<>(new ExceptionResponse(exception.getMessage()), + exception.getHttpStatus()); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleUnexpectedException(Exception exception) { + errorLogging(exception); + + return ResponseEntity.internalServerError() + .body(new ExceptionResponse(String.format("전화 주세요 : %s", exception.getMessage()))); + } + + @ExceptionHandler(DataAccessResourceFailureException.class) + public ResponseEntity handleDatabaseException( + DataAccessResourceFailureException exception) { + errorLogging(exception); + + return new ResponseEntity<>(new ExceptionResponse(exception.getMessage()), + HttpStatus.INTERNAL_SERVER_ERROR); + } + + private void errorLogging(Exception exception) { + log.info( + "클래스 이름 = {} 메시지 = {}", + exception.getClass().getSimpleName(), + exception.getMessage() + ); + } } diff --git a/src/main/java/subway/exception/common/ExceptionResponse.java b/src/main/java/subway/exception/common/ExceptionResponse.java index 421ce15fc..f42af0baa 100644 --- a/src/main/java/subway/exception/common/ExceptionResponse.java +++ b/src/main/java/subway/exception/common/ExceptionResponse.java @@ -2,13 +2,13 @@ public class ExceptionResponse { - private final String message; + private final String message; - public ExceptionResponse(final String message) { - this.message = message; - } + public ExceptionResponse(final String message) { + this.message = message; + } - public String getMessage() { - return message; - } + public String getMessage() { + return message; + } } diff --git a/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java b/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java index e784ad92f..ab1e0509e 100644 --- a/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java +++ b/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java @@ -5,7 +5,7 @@ public class CanNotDuplicatedLineNameException extends BusinessException { - public CanNotDuplicatedLineNameException(final String message) { - super(message, HttpStatus.BAD_REQUEST); - } + public CanNotDuplicatedLineNameException(final String message) { + super(message, HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/subway/exception/line/CanNotFoundLineException.java b/src/main/java/subway/exception/line/CanNotFoundLineException.java index f16c66c1b..82b76996f 100644 --- a/src/main/java/subway/exception/line/CanNotFoundLineException.java +++ b/src/main/java/subway/exception/line/CanNotFoundLineException.java @@ -5,7 +5,7 @@ public class CanNotFoundLineException extends BusinessException { - public CanNotFoundLineException(final String message) { - super(message, HttpStatus.BAD_REQUEST); - } + public CanNotFoundLineException(final String message) { + super(message, HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java b/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java index 68c89f2c7..b4b76dc88 100644 --- a/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java +++ b/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java @@ -5,7 +5,7 @@ public class CanNotDistanceEqualZeroException extends BusinessException { - public CanNotDistanceEqualZeroException(final String message) { - super(message, HttpStatus.BAD_REQUEST); - } + public CanNotDistanceEqualZeroException(final String message) { + super(message, HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java b/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java index 57049ded7..be955cc7f 100644 --- a/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java +++ b/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java @@ -5,7 +5,7 @@ public class CanNotDuplicatedSectionException extends BusinessException { - public CanNotDuplicatedSectionException(final String message) { - super(message, HttpStatus.BAD_REQUEST); - } + public CanNotDuplicatedSectionException(final String message) { + super(message, HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/subway/service/LineCommandService.java b/src/main/java/subway/service/LineCommandService.java index 29e6f39b7..d5165c021 100644 --- a/src/main/java/subway/service/LineCommandService.java +++ b/src/main/java/subway/service/LineCommandService.java @@ -11,39 +11,39 @@ @Transactional public class LineCommandService { - private final LineDao lineDao; - private final SectionCommandService sectionCommandService; - private final LineQueryService lineQueryService; - - public LineCommandService( - final LineDao lineDao, - final SectionCommandService sectionCommandService, - final LineQueryService lineQueryService - ) { - this.lineDao = lineDao; - this.sectionCommandService = sectionCommandService; - this.lineQueryService = lineQueryService; + private final LineDao lineDao; + private final SectionCommandService sectionCommandService; + private final LineQueryService lineQueryService; + + public LineCommandService( + final LineDao lineDao, + final SectionCommandService sectionCommandService, + final LineQueryService lineQueryService + ) { + this.lineDao = lineDao; + this.sectionCommandService = sectionCommandService; + this.lineQueryService = lineQueryService; + } + + public void deleteLine(final Long lineId) { + lineDao.deleteById(lineId); + } + + public void registerLine(final RegisterLineRequest registerLineRequest) { + + final String lineName = registerLineRequest.getLineName(); + + if (lineQueryService.isExistLine(lineName)) { + throw new CanNotDuplicatedLineNameException("이미 등록되어 있는 노선입니다. 노선 이름은 중복될 수 없습니다."); } - public void deleteLine(final Long lineId) { - lineDao.deleteById(lineId); - } - - public void registerLine(final RegisterLineRequest registerLineRequest) { - - final String lineName = registerLineRequest.getLineName(); + final Long savedId = lineDao.save(new LineEntity(lineName)); - if (lineQueryService.isExistLine(lineName)) { - throw new CanNotDuplicatedLineNameException("이미 등록되어 있는 노선입니다. 노선 이름은 중복될 수 없습니다."); - } - - final Long savedId = lineDao.save(new LineEntity(lineName)); - - sectionCommandService.registerSection( - registerLineRequest.getCurrentStationName(), - registerLineRequest.getNextStationName(), - registerLineRequest.getDistance(), - savedId - ); - } + sectionCommandService.registerSection( + registerLineRequest.getCurrentStationName(), + registerLineRequest.getNextStationName(), + registerLineRequest.getDistance(), + savedId + ); + } } diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/service/LineQueryService.java index d68ef9e78..e4672887e 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/service/LineQueryService.java @@ -1,5 +1,7 @@ package subway.service; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.dao.LineDao; @@ -7,69 +9,65 @@ import subway.domain.line.Line; import subway.exception.line.CanNotFoundLineException; -import java.util.List; -import java.util.stream.Collectors; - @Service @Transactional(readOnly = true) public class LineQueryService { - private final LineDao lineDao; - private final SectionQueryService sectionQueryService; + private final LineDao lineDao; + private final SectionQueryService sectionQueryService; - public LineQueryService(final LineDao lineDao, final SectionQueryService sectionQueryService) { - this.lineDao = lineDao; - this.sectionQueryService = sectionQueryService; - } - - public List searchLines(final String lineName) { + public LineQueryService(final LineDao lineDao, final SectionQueryService sectionQueryService) { + this.lineDao = lineDao; + this.sectionQueryService = sectionQueryService; + } - if (lineName == null) { - return searchAllLine(); - } + public List searchLines(final String lineName) { - return List.of(searchByLineName(lineName)); + if (lineName == null) { + return searchAllLine(); } - public List searchAllLine() { - - final List lineEntities = lineDao.findAll(); - - return lineEntities.stream() - .map(lineEntity -> new Line( - lineEntity.getId(), - lineEntity.getName(), - sectionQueryService.searchSectionsByLineId(lineEntity.getId()))) - .collect(Collectors.toList()); - } - - public Line searchByLineName(final String lineName) { - final LineEntity lineEntity = - lineDao.findByLineName(lineName) - .orElseThrow(() -> new CanNotFoundLineException("해당 노선은 존재하지 않습니다.")); - - return new Line( - lineEntity.getId(), - lineEntity.getName(), - sectionQueryService.searchSectionsByLineId(lineEntity.getId()) - ); - } - - public Line searchByLineId(final Long lineId) { - - final LineEntity lineEntity = - lineDao.findByLineId(lineId) - .orElseThrow(() -> new CanNotFoundLineException("해당 노선은 존재하지 않습니다.")); - - return new Line( - lineEntity.getId(), - lineEntity.getName(), - sectionQueryService.searchSectionsByLineId(lineEntity.getId()) - ); - } - - public boolean isExistLine(final String lineName) { - //TODO : Line 에 이름 인덱스 생성해보기 - return lineDao.findByLineName(lineName).isPresent(); - } + return List.of(searchByLineName(lineName)); + } + + public List searchAllLine() { + + final List lineEntities = lineDao.findAll(); + + return lineEntities.stream() + .map(lineEntity -> new Line( + lineEntity.getId(), + lineEntity.getName(), + sectionQueryService.searchSectionsByLineId(lineEntity.getId()))) + .collect(Collectors.toList()); + } + + public Line searchByLineName(final String lineName) { + final LineEntity lineEntity = + lineDao.findByLineName(lineName) + .orElseThrow(() -> new CanNotFoundLineException("해당 노선은 존재하지 않습니다.")); + + return new Line( + lineEntity.getId(), + lineEntity.getName(), + sectionQueryService.searchSectionsByLineId(lineEntity.getId()) + ); + } + + public Line searchByLineId(final Long lineId) { + + final LineEntity lineEntity = + lineDao.findByLineId(lineId) + .orElseThrow(() -> new CanNotFoundLineException("해당 노선은 존재하지 않습니다.")); + + return new Line( + lineEntity.getId(), + lineEntity.getName(), + sectionQueryService.searchSectionsByLineId(lineEntity.getId()) + ); + } + + public boolean isExistLine(final String lineName) { + return lineDao.findByLineName(lineName).isPresent(); + } } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 9b9056a68..c7a020f84 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,5 +1,6 @@ package subway.service; +import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.Money; @@ -10,61 +11,60 @@ import subway.domain.station.Station; import subway.service.dto.ShortestRouteRequest; -import java.util.List; - @Service @Transactional(readOnly = true) public class RouteQueryService { - private final LineQueryService lineQueryService; - private final ChargePolicyComposite chargePolicyComposite; + private final LineQueryService lineQueryService; + private final ChargePolicyComposite chargePolicyComposite; - public RouteQueryService( - final LineQueryService lineQueryService, - final ChargePolicyComposite chargePolicyComposite - ) { - this.lineQueryService = lineQueryService; - this.chargePolicyComposite = chargePolicyComposite; - } + public RouteQueryService( + final LineQueryService lineQueryService, + final ChargePolicyComposite chargePolicyComposite + ) { + this.lineQueryService = lineQueryService; + this.chargePolicyComposite = chargePolicyComposite; + } - public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { + public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { - final List lines = lineQueryService.searchAllLine(); + final List lines = lineQueryService.searchAllLine(); - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) - ); + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) + ); - return route.findShortestRoute(); - } + return route.findShortestRoute(); + } - public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { - final List lines = lineQueryService.searchAllLine(); + public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { + final List lines = lineQueryService.searchAllLine(); - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) - ); + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) + ); - final Money totalPrice = chargePolicyComposite.calculate(route); + final Money totalPrice = chargePolicyComposite.calculate(route); - return chargePolicyComposite.discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) - .getValue(); - } + return chargePolicyComposite.discount(new DiscountCondition(shortestRouteRequest.getAge()), + totalPrice) + .getValue(); + } - public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { - final List lines = lineQueryService.searchAllLine(); + public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { + final List lines = lineQueryService.searchAllLine(); - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) - ); + final Route route = new Route( + lines, + new Station(shortestRouteRequest.getStartStation()), + new Station(shortestRouteRequest.getEndStation()) + ); - return route.findShortestRouteDistance() - .getValue(); - } + return route.findShortestRouteDistance() + .getValue(); + } } diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/service/SectionCommandService.java index 5aa15d543..12ae4a33d 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/service/SectionCommandService.java @@ -1,5 +1,6 @@ package subway.service; +import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.dao.SectionDao; @@ -9,73 +10,72 @@ import subway.domain.station.Stations; import subway.exception.section.CanNotDuplicatedSectionException; -import java.util.List; - @Service @Transactional public class SectionCommandService { - private final SectionDao sectionDao; - private final SectionQueryService sectionQueryService; - - public SectionCommandService(final SectionDao sectionDao, final SectionQueryService sectionQueryService) { - this.sectionDao = sectionDao; - this.sectionQueryService = sectionQueryService; + private final SectionDao sectionDao; + private final SectionQueryService sectionQueryService; + + public SectionCommandService(final SectionDao sectionDao, + final SectionQueryService sectionQueryService) { + this.sectionDao = sectionDao; + this.sectionQueryService = sectionQueryService; + } + + public void registerSection( + final String currentStationName, + final String nextStationName, + final int distance, + final Long lineId + ) { + + final List
originSections = sectionQueryService.searchSectionsByLineId(lineId); + + final Section targetSection = new Section( + new Stations( + new Station(currentStationName), + new Station(nextStationName), + distance + ) + ); + + if (hasSameSection(targetSection, originSections)) { + throw new CanNotDuplicatedSectionException("해당 호선에 이미 출발지와 도착지가 같은 구간이 존재합니다."); } - public void registerSection( - final String currentStationName, - final String nextStationName, - final int distance, - final Long lineId - ) { - - final List
originSections = sectionQueryService.searchSectionsByLineId(lineId); - - final Section targetSection = new Section( - new Stations( - new Station(currentStationName), - new Station(nextStationName), - distance - ) - ); - - if (hasSameSection(targetSection, originSections)) { - throw new CanNotDuplicatedSectionException("해당 호선에 이미 출발지와 도착지가 같은 구간이 존재합니다."); - } - - final SectionEntity sectionEntity = new SectionEntity( - currentStationName, - nextStationName, - distance, - lineId - ); - - sectionDao.save(sectionEntity); - } + final SectionEntity sectionEntity = new SectionEntity( + currentStationName, + nextStationName, + distance, + lineId + ); - private boolean hasSameSection(final Section target, final List
originSections) { - return originSections.stream() - .anyMatch(section -> section.isSame(target)); - } + sectionDao.save(sectionEntity); + } - public void deleteAll(final Long lineId) { - sectionDao.deleteAll(lineId); - } + private boolean hasSameSection(final Section target, final List
originSections) { + return originSections.stream() + .anyMatch(section -> section.isSame(target)); + } - public void deleteSectionById(final Long sectionId) { - sectionDao.deleteById(sectionId); - } + public void deleteAll(final Long lineId) { + sectionDao.deleteAll(lineId); + } - public void updateSection(final Section section) { + public void deleteSectionById(final Long sectionId) { + sectionDao.deleteById(sectionId); + } - final SectionEntity sectionEntity = new SectionEntity( - section.getId(), - section.getStations().getCurrent().getName(), - section.getStations().getNext().getName(), - section.getStations().getDistance() - ); + public void updateSection(final Section section) { - sectionDao.update(sectionEntity); - } + final SectionEntity sectionEntity = new SectionEntity( + section.getId(), + section.getStations().getCurrent().getName(), + section.getStations().getNext().getName(), + section.getStations().getDistance() + ); + + sectionDao.update(sectionEntity); + } } diff --git a/src/main/java/subway/service/SectionQueryService.java b/src/main/java/subway/service/SectionQueryService.java index d6f5068fe..47b3ad337 100644 --- a/src/main/java/subway/service/SectionQueryService.java +++ b/src/main/java/subway/service/SectionQueryService.java @@ -1,5 +1,7 @@ package subway.service; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.dao.SectionDao; @@ -8,33 +10,30 @@ import subway.domain.station.Station; import subway.domain.station.Stations; -import java.util.List; -import java.util.stream.Collectors; - @Service @Transactional(readOnly = true) public class SectionQueryService { - private final SectionDao sectionDao; + private final SectionDao sectionDao; - public SectionQueryService(final SectionDao sectionDao) { - this.sectionDao = sectionDao; - } + public SectionQueryService(final SectionDao sectionDao) { + this.sectionDao = sectionDao; + } - public List
searchSectionsByLineId(final Long lineId) { - return sectionDao.findSectionsByLineId(lineId) - .stream() - .map(this::mapToSectionFrom) - .collect(Collectors.toList()); - } + public List
searchSectionsByLineId(final Long lineId) { + return sectionDao.findSectionsByLineId(lineId) + .stream() + .map(this::mapToSectionFrom) + .collect(Collectors.toList()); + } - private Section mapToSectionFrom(final SectionEntity sectionEntity) { - final Stations stations = new Stations( - new Station(sectionEntity.getCurrentStationName()), - new Station(sectionEntity.getNextStationName()), - sectionEntity.getDistance() - ); + private Section mapToSectionFrom(final SectionEntity sectionEntity) { + final Stations stations = new Stations( + new Station(sectionEntity.getCurrentStationName()), + new Station(sectionEntity.getNextStationName()), + sectionEntity.getDistance() + ); - return new Section(sectionEntity.getId(), stations); - } + return new Section(sectionEntity.getId(), stations); + } } diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java index 371304184..545431fc4 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/service/StationService.java @@ -1,5 +1,8 @@ package subway.service; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.line.Line; @@ -9,110 +12,106 @@ import subway.service.dto.StationDeleteRequest; import subway.service.dto.StationRegisterRequest; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - @Service @Transactional public class StationService { - private final SectionCommandService sectionCommandService; - private final LineCommandService lineCommandService; - private final LineQueryService lineQueryService; - - public StationService( - final SectionCommandService sectionCommandService, - final LineCommandService lineCommandService, - final LineQueryService lineQueryService - ) { - this.sectionCommandService = sectionCommandService; - this.lineCommandService = lineCommandService; - this.lineQueryService = lineQueryService; - } - - public void registerStation(final StationRegisterRequest stationRegisterRequest) { + private final SectionCommandService sectionCommandService; + private final LineCommandService lineCommandService; + private final LineQueryService lineQueryService; - final String lineName = stationRegisterRequest.getLineName(); - final Line line = lineQueryService.searchByLineName(lineName); - final List
originSection = line.getSections(); - final Section newSection = mapToSectionFrom(stationRegisterRequest); + public StationService( + final SectionCommandService sectionCommandService, + final LineCommandService lineCommandService, + final LineQueryService lineQueryService + ) { + this.sectionCommandService = sectionCommandService; + this.lineCommandService = lineCommandService; + this.lineQueryService = lineQueryService; + } - line.add(newSection); + public void registerStation(final StationRegisterRequest stationRegisterRequest) { - sectionCommandService.registerSection( - stationRegisterRequest.getCurrentStationName(), - stationRegisterRequest.getNextStationName(), - stationRegisterRequest.getDistance(), - line.getId() - ); + final String lineName = stationRegisterRequest.getLineName(); + final Line line = lineQueryService.searchByLineName(lineName); + final List
originSection = line.getSections(); + final Section newSection = mapToSectionFrom(stationRegisterRequest); - final List
updatedSection = line.getSections(); + line.add(newSection); - updatedSection.stream() - .filter(section -> originSection.stream().noneMatch(section::isSame)) - .filter(section -> Objects.nonNull(section.getId())) - .findFirst() - .ifPresent(sectionCommandService::updateSection); - } + sectionCommandService.registerSection( + stationRegisterRequest.getCurrentStationName(), + stationRegisterRequest.getNextStationName(), + stationRegisterRequest.getDistance(), + line.getId() + ); - private Section mapToSectionFrom(final StationRegisterRequest stationRegisterRequest) { - final Stations newStations = new Stations( - new Station(stationRegisterRequest.getCurrentStationName()), - new Station(stationRegisterRequest.getNextStationName()), - stationRegisterRequest.getDistance() - ); + final List
updatedSection = line.getSections(); - return new Section(newStations); - } + updatedSection.stream() + .filter(section -> originSection.stream().noneMatch(section::isSame)) + .filter(section -> Objects.nonNull(section.getId())) + .findFirst() + .ifPresent(sectionCommandService::updateSection); + } - public void deleteStation(final StationDeleteRequest stationDeleteRequest) { + private Section mapToSectionFrom(final StationRegisterRequest stationRegisterRequest) { + final Stations newStations = new Stations( + new Station(stationRegisterRequest.getCurrentStationName()), + new Station(stationRegisterRequest.getNextStationName()), + stationRegisterRequest.getDistance() + ); - final String lineName = stationDeleteRequest.getLineName(); - final Line line = lineQueryService.searchByLineName(lineName); + return new Section(newStations); + } - final List
originSection = line.getSections(); + public void deleteStation(final StationDeleteRequest stationDeleteRequest) { - line.delete(new Station(stationDeleteRequest.getStationName())); + final String lineName = stationDeleteRequest.getLineName(); + final Line line = lineQueryService.searchByLineName(lineName); - final List
updatedSection = line.getSections(); + final List
originSection = line.getSections(); - updatedSection.stream() - .filter(section -> originSection.stream().noneMatch(section::isSame)) - .findAny() - .ifPresentOrElse( - updateAndDeleteSection(originSection, updatedSection), - onlyDeleteSection(originSection, updatedSection) - ); + line.delete(new Station(stationDeleteRequest.getStationName())); - if (line.isDeleted()) { - sectionCommandService.deleteAll(line.getId()); - lineCommandService.deleteLine(line.getId()); - } - } + final List
updatedSection = line.getSections(); - private Consumer
updateAndDeleteSection( - final List
originSection, - final List
updatedSection - ) { - return section -> { - sectionCommandService.updateSection(section); - - originSection.stream() - .filter(origin -> updatedSection.stream().noneMatch(origin::isSame)) - .filter(origin -> !origin.equals(section)) - .findFirst() - .ifPresent(origin -> sectionCommandService.deleteSectionById(origin.getId())); - }; - } + updatedSection.stream() + .filter(section -> originSection.stream().noneMatch(section::isSame)) + .findAny() + .ifPresentOrElse( + updateAndDeleteSection(originSection, updatedSection), + onlyDeleteSection(originSection, updatedSection) + ); - private Runnable onlyDeleteSection( - final List
originSection, - final List
updatedSection - ) { - return () -> originSection.stream() - .filter(section -> updatedSection.stream().noneMatch(section::isSame)) - .findFirst() - .ifPresent(section -> sectionCommandService.deleteSectionById(section.getId())); + if (line.isDeleted()) { + sectionCommandService.deleteAll(line.getId()); + lineCommandService.deleteLine(line.getId()); } + } + + private Consumer
updateAndDeleteSection( + final List
originSection, + final List
updatedSection + ) { + return section -> { + sectionCommandService.updateSection(section); + + originSection.stream() + .filter(origin -> updatedSection.stream().noneMatch(origin::isSame)) + .filter(origin -> !origin.equals(section)) + .findFirst() + .ifPresent(origin -> sectionCommandService.deleteSectionById(origin.getId())); + }; + } + + private Runnable onlyDeleteSection( + final List
originSection, + final List
updatedSection + ) { + return () -> originSection.stream() + .filter(section -> updatedSection.stream().noneMatch(section::isSame)) + .findFirst() + .ifPresent(section -> sectionCommandService.deleteSectionById(section.getId())); + } } diff --git a/src/main/java/subway/service/dto/LeastCostRouteResponse.java b/src/main/java/subway/service/dto/LeastCostRouteResponse.java index 074e83abd..6d5a107d7 100644 --- a/src/main/java/subway/service/dto/LeastCostRouteResponse.java +++ b/src/main/java/subway/service/dto/LeastCostRouteResponse.java @@ -2,36 +2,36 @@ public class LeastCostRouteResponse { - private final String startStation; - private final String endStation; - private final int cost; - private final int distance; + private final String startStation; + private final String endStation; + private final int cost; + private final int distance; - public LeastCostRouteResponse( - final String startStation, - final String endStation, - final int cost, - final int distance - ) { - this.startStation = startStation; - this.endStation = endStation; - this.cost = cost; - this.distance = distance; - } + public LeastCostRouteResponse( + final String startStation, + final String endStation, + final int cost, + final int distance + ) { + this.startStation = startStation; + this.endStation = endStation; + this.cost = cost; + this.distance = distance; + } - public String getStartStation() { - return startStation; - } + public String getStartStation() { + return startStation; + } - public String getEndStation() { - return endStation; - } + public String getEndStation() { + return endStation; + } - public int getCost() { - return cost; - } + public int getCost() { + return cost; + } - public int getDistance() { - return distance; - } + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/service/dto/LineResponse.java b/src/main/java/subway/service/dto/LineResponse.java index 5208f9111..0bf844869 100644 --- a/src/main/java/subway/service/dto/LineResponse.java +++ b/src/main/java/subway/service/dto/LineResponse.java @@ -4,25 +4,26 @@ public class LineResponse { - private final String lineName; - private final List sections; - private final Long lineId; + private final String lineName; + private final List sections; + private final Long lineId; - public LineResponse(final String lineName, final List sections, final Long lineId) { - this.lineName = lineName; - this.sections = sections; - this.lineId = lineId; - } + public LineResponse(final String lineName, final List sections, + final Long lineId) { + this.lineName = lineName; + this.sections = sections; + this.lineId = lineId; + } - public String getLineName() { - return lineName; - } + public String getLineName() { + return lineName; + } - public List getSections() { - return sections; - } + public List getSections() { + return sections; + } - public Long getLineId() { - return lineId; - } + public Long getLineId() { + return lineId; + } } diff --git a/src/main/java/subway/service/dto/RegisterLineRequest.java b/src/main/java/subway/service/dto/RegisterLineRequest.java index 895010eb4..bdf7471a8 100644 --- a/src/main/java/subway/service/dto/RegisterLineRequest.java +++ b/src/main/java/subway/service/dto/RegisterLineRequest.java @@ -2,39 +2,39 @@ public class RegisterLineRequest { - private String currentStationName; - private String nextStationName; - private String lineName; - private int distance; - - private RegisterLineRequest() { - } - - public RegisterLineRequest( - final String currentStationName, - final String nextStationName, - final String lineName, - final int distance - ) { - this.currentStationName = currentStationName; - this.nextStationName = nextStationName; - this.lineName = lineName; - this.distance = distance; - } - - public String getCurrentStationName() { - return currentStationName; - } - - public String getNextStationName() { - return nextStationName; - } - - public String getLineName() { - return lineName; - } - - public int getDistance() { - return distance; - } + private String currentStationName; + private String nextStationName; + private String lineName; + private int distance; + + private RegisterLineRequest() { + } + + public RegisterLineRequest( + final String currentStationName, + final String nextStationName, + final String lineName, + final int distance + ) { + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.lineName = lineName; + this.distance = distance; + } + + public String getCurrentStationName() { + return currentStationName; + } + + public String getNextStationName() { + return nextStationName; + } + + public String getLineName() { + return lineName; + } + + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/service/dto/SectionResponse.java b/src/main/java/subway/service/dto/SectionResponse.java index 4bc19663d..847386d09 100644 --- a/src/main/java/subway/service/dto/SectionResponse.java +++ b/src/main/java/subway/service/dto/SectionResponse.java @@ -2,25 +2,26 @@ public class SectionResponse { - private final String currentStationName; - private final String nextStationName; - private final int distance; + private final String currentStationName; + private final String nextStationName; + private final int distance; - public SectionResponse(final String currentStationName, final String nextStationName, final int distance) { - this.currentStationName = currentStationName; - this.nextStationName = nextStationName; - this.distance = distance; - } + public SectionResponse(final String currentStationName, final String nextStationName, + final int distance) { + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.distance = distance; + } - public String getCurrentStationName() { - return currentStationName; - } + public String getCurrentStationName() { + return currentStationName; + } - public String getNextStationName() { - return nextStationName; - } + public String getNextStationName() { + return nextStationName; + } - public int getDistance() { - return distance; - } + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/service/dto/ShortestRouteRequest.java b/src/main/java/subway/service/dto/ShortestRouteRequest.java index 339bfe2b0..7ee988d1b 100644 --- a/src/main/java/subway/service/dto/ShortestRouteRequest.java +++ b/src/main/java/subway/service/dto/ShortestRouteRequest.java @@ -2,25 +2,26 @@ public class ShortestRouteRequest { - private final String startStation; - private final String endStation; - private final Integer age; + private final String startStation; + private final String endStation; + private final Integer age; - public ShortestRouteRequest(final String startStation, final String endStation, final Integer age) { - this.startStation = startStation; - this.endStation = endStation; - this.age = age; - } + public ShortestRouteRequest(final String startStation, final String endStation, + final Integer age) { + this.startStation = startStation; + this.endStation = endStation; + this.age = age; + } - public String getStartStation() { - return startStation; - } + public String getStartStation() { + return startStation; + } - public String getEndStation() { - return endStation; - } + public String getEndStation() { + return endStation; + } - public Integer getAge() { - return age; - } + public Integer getAge() { + return age; + } } diff --git a/src/main/java/subway/service/dto/ShortestRouteResponse.java b/src/main/java/subway/service/dto/ShortestRouteResponse.java index d156c6e29..9fb3ab87f 100644 --- a/src/main/java/subway/service/dto/ShortestRouteResponse.java +++ b/src/main/java/subway/service/dto/ShortestRouteResponse.java @@ -4,25 +4,25 @@ public class ShortestRouteResponse { - private final List stations; - private final double cost; - private final int distance; + private final List stations; + private final double cost; + private final int distance; - public ShortestRouteResponse(final List stations, final double cost, final int distance) { - this.stations = stations; - this.cost = cost; - this.distance = distance; - } + public ShortestRouteResponse(final List stations, final double cost, final int distance) { + this.stations = stations; + this.cost = cost; + this.distance = distance; + } - public List getStations() { - return stations; - } + public List getStations() { + return stations; + } - public double getCost() { - return cost; - } + public double getCost() { + return cost; + } - public int getDistance() { - return distance; - } + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/service/dto/StationDeleteRequest.java b/src/main/java/subway/service/dto/StationDeleteRequest.java index db194a244..6201efe3a 100644 --- a/src/main/java/subway/service/dto/StationDeleteRequest.java +++ b/src/main/java/subway/service/dto/StationDeleteRequest.java @@ -2,22 +2,22 @@ public class StationDeleteRequest { - private String lineName; - private String stationName; + private String lineName; + private String stationName; - private StationDeleteRequest() { - } + private StationDeleteRequest() { + } - public StationDeleteRequest(final String lineName, final String stationName) { - this.lineName = lineName; - this.stationName = stationName; - } + public StationDeleteRequest(final String lineName, final String stationName) { + this.lineName = lineName; + this.stationName = stationName; + } - public String getLineName() { - return lineName; - } + public String getLineName() { + return lineName; + } - public String getStationName() { - return stationName; - } + public String getStationName() { + return stationName; + } } diff --git a/src/main/java/subway/service/dto/StationRegisterRequest.java b/src/main/java/subway/service/dto/StationRegisterRequest.java index 8620cf6a8..aba166957 100644 --- a/src/main/java/subway/service/dto/StationRegisterRequest.java +++ b/src/main/java/subway/service/dto/StationRegisterRequest.java @@ -2,39 +2,39 @@ public class StationRegisterRequest { - private String lineName; - private String currentStationName; - private String nextStationName; - private int distance; - - private StationRegisterRequest() { - } - - public StationRegisterRequest( - final String lineName, - final String currentStationName, - final String nextStationName, - final int distance - ) { - this.lineName = lineName; - this.currentStationName = currentStationName; - this.nextStationName = nextStationName; - this.distance = distance; - } - - public String getLineName() { - return lineName; - } - - public String getCurrentStationName() { - return currentStationName; - } - - public String getNextStationName() { - return nextStationName; - } - - public int getDistance() { - return distance; - } + private String lineName; + private String currentStationName; + private String nextStationName; + private int distance; + + private StationRegisterRequest() { + } + + public StationRegisterRequest( + final String lineName, + final String currentStationName, + final String nextStationName, + final int distance + ) { + this.lineName = lineName; + this.currentStationName = currentStationName; + this.nextStationName = nextStationName; + this.distance = distance; + } + + public String getLineName() { + return lineName; + } + + public String getCurrentStationName() { + return currentStationName; + } + + public String getNextStationName() { + return nextStationName; + } + + public int getDistance() { + return distance; + } } diff --git a/src/main/java/subway/service/dto/StationRegisterResponse.java b/src/main/java/subway/service/dto/StationRegisterResponse.java index ca0e5c3e8..97ef9b2bf 100644 --- a/src/main/java/subway/service/dto/StationRegisterResponse.java +++ b/src/main/java/subway/service/dto/StationRegisterResponse.java @@ -2,19 +2,19 @@ public class StationRegisterResponse { - private String lineName; - private String stationName; + private String lineName; + private String stationName; - public StationRegisterResponse(final String lineName, final String stationName) { - this.lineName = lineName; - this.stationName = stationName; - } + public StationRegisterResponse(final String lineName, final String stationName) { + this.lineName = lineName; + this.stationName = stationName; + } - public String getLineName() { - return lineName; - } + public String getLineName() { + return lineName; + } - public String getStationName() { - return stationName; - } + public String getStationName() { + return stationName; + } } From 89a3d4aaaa4110a53b02d4c9b8833a9cbe15026b Mon Sep 17 00:00:00 2001 From: java-saeng Date: Wed, 24 May 2023 00:14:29 +0900 Subject: [PATCH 30/41] =?UTF-8?q?refactor=20:=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최소 요금이 아닌 최단거리에 대한 요금을 구하는 메서드임 --- .../subway/controller/RouteController.java | 2 +- .../subway/service/RouteQueryService.java | 6 +- .../controller/RouteControllerTest.java | 103 ++++++++------- .../subway/service/RouteQueryServiceTest.java | 123 +++++++++--------- 4 files changed, 116 insertions(+), 118 deletions(-) diff --git a/src/main/java/subway/controller/RouteController.java b/src/main/java/subway/controller/RouteController.java index 48793ea71..7f7de2d59 100644 --- a/src/main/java/subway/controller/RouteController.java +++ b/src/main/java/subway/controller/RouteController.java @@ -21,7 +21,7 @@ public ShortestRouteResponse showShortestRoute( @ModelAttribute ShortestRouteRequest shortestRouteRequest) { return new ShortestRouteResponse( routeQueryService.searchShortestRoute(shortestRouteRequest), - routeQueryService.searchLeastCost(shortestRouteRequest), + routeQueryService.searchCost(shortestRouteRequest), routeQueryService.searchShortestDistance(shortestRouteRequest) ); } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index c7a020f84..ef739b97e 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -39,7 +39,7 @@ public List searchShortestRoute(final ShortestRouteRequest shortestRoute return route.findShortestRoute(); } - public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { + public double searchCost(final ShortestRouteRequest shortestRouteRequest) { final List lines = lineQueryService.searchAllLine(); final Route route = new Route( @@ -50,8 +50,8 @@ public double searchLeastCost(final ShortestRouteRequest shortestRouteRequest) { final Money totalPrice = chargePolicyComposite.calculate(route); - return chargePolicyComposite.discount(new DiscountCondition(shortestRouteRequest.getAge()), - totalPrice) + return chargePolicyComposite + .discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) .getValue(); } diff --git a/src/test/java/subway/controller/RouteControllerTest.java b/src/test/java/subway/controller/RouteControllerTest.java index 88d36b443..7139e43f0 100644 --- a/src/test/java/subway/controller/RouteControllerTest.java +++ b/src/test/java/subway/controller/RouteControllerTest.java @@ -1,5 +1,11 @@ package subway.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -8,72 +14,65 @@ import org.springframework.test.web.servlet.MockMvc; import subway.service.RouteQueryService; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @WebMvcTest(RouteController.class) class RouteControllerTest { - @Autowired - private MockMvc mockMvc; + @Autowired + private MockMvc mockMvc; - @MockBean - private RouteQueryService routeQueryService; + @MockBean + private RouteQueryService routeQueryService; - @Test - @DisplayName("showShortestRoute() : 출발, 도착역이 주어지고, 나이가 주어지지 않으면 추가 요금 없이 최단 경로와 가격을 조회되면 200 OK를 반환한다.") - void test_showShortestRoute() throws Exception { - //given - final String startStationName = "A"; - final String endStationName = "B"; + @Test + @DisplayName("showShortestRoute() : 출발, 도착역이 주어지고, 나이가 주어지지 않으면 추가 요금 없이 최단 경로와 가격을 조회되면 200 OK를 반환한다.") + void test_showShortestRoute() throws Exception { + //given + final String startStationName = "A"; + final String endStationName = "B"; - final List shortestRoute = List.of("A", "K", "Z", "B"); - final double leastCost = 100d; - final int shortestDistance = 10; + final List shortestRoute = List.of("A", "K", "Z", "B"); + final double leastCost = 100d; + final int shortestDistance = 10; - when(routeQueryService.searchShortestRoute(any())) - .thenReturn(shortestRoute); + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRoute); - when(routeQueryService.searchLeastCost(any())) - .thenReturn(leastCost); + when(routeQueryService.searchCost(any())) + .thenReturn(leastCost); - when(routeQueryService.searchShortestDistance(any())) - .thenReturn(shortestDistance); + when(routeQueryService.searchShortestDistance(any())) + .thenReturn(shortestDistance); - //then - mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}", - startStationName, endStationName)) - .andExpect(status().isOk()); - } + //then + mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}", + startStationName, endStationName)) + .andExpect(status().isOk()); + } - @Test - @DisplayName("showShortestRoute() : 나이가 주어지면 나이에 따른 요금이 추가된 최단 경로와 가격을 조회되면 200 OK를 반환한다.") - void test_showShortestRoute_age() throws Exception { - //given - final String startStationName = "A"; - final String endStationName = "B"; - final Integer age = 14; + @Test + @DisplayName("showShortestRoute() : 나이가 주어지면 나이에 따른 요금이 추가된 최단 경로와 가격을 조회되면 200 OK를 반환한다.") + void test_showShortestRoute_age() throws Exception { + //given + final String startStationName = "A"; + final String endStationName = "B"; + final Integer age = 14; - final List shortestRoute = List.of("A", "K", "Z", "B"); - final double leastCost = 100d; - final int shortestDistance = 10; + final List shortestRoute = List.of("A", "K", "Z", "B"); + final double leastCost = 100d; + final int shortestDistance = 10; - when(routeQueryService.searchShortestRoute(any())) - .thenReturn(shortestRoute); + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRoute); - when(routeQueryService.searchLeastCost(any())) - .thenReturn(leastCost); + when(routeQueryService.searchCost(any())) + .thenReturn(leastCost); - when(routeQueryService.searchShortestDistance(any())) - .thenReturn(shortestDistance); + when(routeQueryService.searchShortestDistance(any())) + .thenReturn(shortestDistance); - //then - mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}&age={age}", - startStationName, endStationName, age)) - .andExpect(status().isOk()); - } + //then + mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}&age={age}", + startStationName, endStationName, age)) + .andExpect(status().isOk()); + } } diff --git a/src/test/java/subway/service/RouteQueryServiceTest.java b/src/test/java/subway/service/RouteQueryServiceTest.java index d274a0217..0e32e7143 100644 --- a/src/test/java/subway/service/RouteQueryServiceTest.java +++ b/src/test/java/subway/service/RouteQueryServiceTest.java @@ -1,73 +1,72 @@ package subway.service; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + import helper.IntegrationTestHelper; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import subway.service.dto.ShortestRouteRequest; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; - class RouteQueryServiceTest extends IntegrationTestHelper { - @Autowired - private RouteQueryService routeQueryService; - - @Test - @DisplayName("searchShortestRoute() : 출발, 도착역을 통해 최소 경로를 조회할 수 있다.") - void test_searchShortestRoute() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "D"; - - final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, null); - - //when - final List route = routeQueryService.searchShortestRoute(shortestRouteRequest); - - //then - assertThat(route).containsAnyElementsOf(List.of("A", "B", "C", "D")); - } - - @Test - @DisplayName("searchLeastCost() : 나이와 특정 호선에 따라서 최소 요금 정보를 조회할 수 있다.") - void test_searchLeastCost() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "D"; - final Integer age = 14; - - final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, age); - - //when - final double fare = routeQueryService.searchLeastCost(shortestRouteRequest); - - //then - //부과 : 1호선 가격 : 500, 기본 요금 : 1250 - //할인 : 청소년 -350, -20% - assertEquals(1120d, fare); - } - - @Test - @DisplayName("searchShortestDistance() : 출발, 도착역 간의 최소 경로 거리를 조회할 수 있다.") - void test_searchShortestDistance() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "D"; - final Integer age = null; - - final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, age); - - //when - final int distance = routeQueryService.searchShortestDistance(shortestRouteRequest); - - //then - assertEquals(6, distance); - } + @Autowired + private RouteQueryService routeQueryService; + + @Test + @DisplayName("searchShortestRoute() : 출발, 도착역을 통해 최소 경로를 조회할 수 있다.") + void test_searchShortestRoute() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, null); + + //when + final List route = routeQueryService.searchShortestRoute(shortestRouteRequest); + + //then + assertThat(route).containsAnyElementsOf(List.of("A", "B", "C", "D")); + } + + @Test + @DisplayName("searchLeastCost() : 나이와 특정 호선에 따라서 최소 요금 정보를 조회할 수 있다.") + void test_searchLeastCost() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + final Integer age = 14; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, age); + + //when + final double fare = routeQueryService.searchCost(shortestRouteRequest); + + //then + //부과 : 1호선 가격 : 500, 기본 요금 : 1250 + //할인 : 청소년 -350, -20% + assertEquals(1120d, fare); + } + + @Test + @DisplayName("searchShortestDistance() : 출발, 도착역 간의 최소 경로 거리를 조회할 수 있다.") + void test_searchShortestDistance() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "D"; + final Integer age = null; + + final ShortestRouteRequest shortestRouteRequest = + new ShortestRouteRequest(currentStationName, nextStationName, age); + + //when + final int distance = routeQueryService.searchShortestDistance(shortestRouteRequest); + + //then + assertEquals(6, distance); + } } From 7a95accd653233880ef9c831f3aef085d2254e70 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Wed, 24 May 2023 00:32:41 +0900 Subject: [PATCH 31/41] =?UTF-8?q?refactor=20:=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=ED=95=98=EB=82=98=EC=9D=98=20?= =?UTF-8?q?service=20=EC=97=90=EC=84=9C=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 굳이 세 개의 메서드에서 매번 Route를 만들면서 할 필요가 없어서 하나로 합침 --- .../subway/controller/RouteController.java | 9 ++-- .../subway/service/RouteQueryService.java | 39 +++++--------- .../controller/RouteControllerTest.java | 23 ++++---- .../subway/service/RouteQueryServiceTest.java | 54 +++++-------------- 4 files changed, 38 insertions(+), 87 deletions(-) diff --git a/src/main/java/subway/controller/RouteController.java b/src/main/java/subway/controller/RouteController.java index 7f7de2d59..02460235b 100644 --- a/src/main/java/subway/controller/RouteController.java +++ b/src/main/java/subway/controller/RouteController.java @@ -18,11 +18,8 @@ public RouteController(final RouteQueryService routeQueryService) { @GetMapping("/route") public ShortestRouteResponse showShortestRoute( - @ModelAttribute ShortestRouteRequest shortestRouteRequest) { - return new ShortestRouteResponse( - routeQueryService.searchShortestRoute(shortestRouteRequest), - routeQueryService.searchCost(shortestRouteRequest), - routeQueryService.searchShortestDistance(shortestRouteRequest) - ); + @ModelAttribute ShortestRouteRequest shortestRouteRequest + ) { + return routeQueryService.searchShortestRoute(shortestRouteRequest); } } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index ef739b97e..69dbffb47 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import subway.domain.Distance; import subway.domain.Money; import subway.domain.line.Line; import subway.domain.policy.ChargePolicyComposite; @@ -10,6 +11,7 @@ import subway.domain.route.Route; import subway.domain.station.Station; import subway.service.dto.ShortestRouteRequest; +import subway.service.dto.ShortestRouteResponse; @Service @Transactional(readOnly = true) @@ -26,7 +28,9 @@ public RouteQueryService( this.chargePolicyComposite = chargePolicyComposite; } - public List searchShortestRoute(final ShortestRouteRequest shortestRouteRequest) { + public ShortestRouteResponse searchShortestRoute( + final ShortestRouteRequest shortestRouteRequest + ) { final List lines = lineQueryService.searchAllLine(); @@ -36,35 +40,20 @@ public List searchShortestRoute(final ShortestRouteRequest shortestRoute new Station(shortestRouteRequest.getEndStation()) ); - return route.findShortestRoute(); - } - - public double searchCost(final ShortestRouteRequest shortestRouteRequest) { - final List lines = lineQueryService.searchAllLine(); - - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) + return new ShortestRouteResponse( + route.findShortestRoute(), + searchCost(route, shortestRouteRequest.getAge()).getValue(), + searchShortestDistance(route).getValue() ); + } + private Money searchCost(final Route route, final Integer age) { final Money totalPrice = chargePolicyComposite.calculate(route); - return chargePolicyComposite - .discount(new DiscountCondition(shortestRouteRequest.getAge()), totalPrice) - .getValue(); + return chargePolicyComposite.discount(new DiscountCondition(age), totalPrice); } - public int searchShortestDistance(final ShortestRouteRequest shortestRouteRequest) { - final List lines = lineQueryService.searchAllLine(); - - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) - ); - - return route.findShortestRouteDistance() - .getValue(); + private Distance searchShortestDistance(final Route route) { + return route.findShortestRouteDistance(); } } diff --git a/src/test/java/subway/controller/RouteControllerTest.java b/src/test/java/subway/controller/RouteControllerTest.java index 7139e43f0..bc9ee30fa 100644 --- a/src/test/java/subway/controller/RouteControllerTest.java +++ b/src/test/java/subway/controller/RouteControllerTest.java @@ -13,6 +13,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; import subway.service.RouteQueryService; +import subway.service.dto.ShortestRouteResponse; @WebMvcTest(RouteController.class) class RouteControllerTest { @@ -34,14 +35,11 @@ void test_showShortestRoute() throws Exception { final double leastCost = 100d; final int shortestDistance = 10; - when(routeQueryService.searchShortestRoute(any())) - .thenReturn(shortestRoute); - - when(routeQueryService.searchCost(any())) - .thenReturn(leastCost); + ShortestRouteResponse shortestRouteResponse = new ShortestRouteResponse(shortestRoute, + leastCost, shortestDistance); - when(routeQueryService.searchShortestDistance(any())) - .thenReturn(shortestDistance); + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRouteResponse); //then mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}", @@ -61,14 +59,11 @@ void test_showShortestRoute_age() throws Exception { final double leastCost = 100d; final int shortestDistance = 10; - when(routeQueryService.searchShortestRoute(any())) - .thenReturn(shortestRoute); - - when(routeQueryService.searchCost(any())) - .thenReturn(leastCost); + ShortestRouteResponse shortestRouteResponse = new ShortestRouteResponse(shortestRoute, + leastCost, shortestDistance); - when(routeQueryService.searchShortestDistance(any())) - .thenReturn(shortestDistance); + when(routeQueryService.searchShortestRoute(any())) + .thenReturn(shortestRouteResponse); //then mockMvc.perform(get("/route?startStation={startStation}&endStation={endStation}&age={age}", diff --git a/src/test/java/subway/service/RouteQueryServiceTest.java b/src/test/java/subway/service/RouteQueryServiceTest.java index 0e32e7143..0284f36c3 100644 --- a/src/test/java/subway/service/RouteQueryServiceTest.java +++ b/src/test/java/subway/service/RouteQueryServiceTest.java @@ -1,6 +1,7 @@ package subway.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import helper.IntegrationTestHelper; @@ -9,6 +10,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import subway.service.dto.ShortestRouteRequest; +import subway.service.dto.ShortestRouteResponse; class RouteQueryServiceTest extends IntegrationTestHelper { @@ -16,57 +18,25 @@ class RouteQueryServiceTest extends IntegrationTestHelper { private RouteQueryService routeQueryService; @Test - @DisplayName("searchShortestRoute() : 출발, 도착역을 통해 최소 경로를 조회할 수 있다.") + @DisplayName("searchShortestRoute() : 출발, 도착역을 통해 최소 경로, 요금, 거리를 구할 수 있다.") void test_searchShortestRoute() throws Exception { //given final String currentStationName = "A"; final String nextStationName = "D"; final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, null); + new ShortestRouteRequest(currentStationName, nextStationName, 14); //when - final List route = routeQueryService.searchShortestRoute(shortestRouteRequest); + ShortestRouteResponse shortestRouteResponse = routeQueryService.searchShortestRoute( + shortestRouteRequest); //then - assertThat(route).containsAnyElementsOf(List.of("A", "B", "C", "D")); - } - - @Test - @DisplayName("searchLeastCost() : 나이와 특정 호선에 따라서 최소 요금 정보를 조회할 수 있다.") - void test_searchLeastCost() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "D"; - final Integer age = 14; - - final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, age); - - //when - final double fare = routeQueryService.searchCost(shortestRouteRequest); - - //then - //부과 : 1호선 가격 : 500, 기본 요금 : 1250 - //할인 : 청소년 -350, -20% - assertEquals(1120d, fare); - } - - @Test - @DisplayName("searchShortestDistance() : 출발, 도착역 간의 최소 경로 거리를 조회할 수 있다.") - void test_searchShortestDistance() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "D"; - final Integer age = null; - - final ShortestRouteRequest shortestRouteRequest = - new ShortestRouteRequest(currentStationName, nextStationName, age); - - //when - final int distance = routeQueryService.searchShortestDistance(shortestRouteRequest); - - //then - assertEquals(6, distance); + assertAll( + () -> assertThat(shortestRouteResponse.getStations()).containsAnyElementsOf( + List.of("A", "B", "C", "D")), + () -> assertEquals(1120d, shortestRouteResponse.getCost()), + () -> assertEquals(6, shortestRouteResponse.getDistance()) + ); } } From beded7a55b88dab29e7eefc198312fcc46eec1ca Mon Sep 17 00:00:00 2001 From: java-saeng Date: Wed, 24 May 2023 00:39:46 +0900 Subject: [PATCH 32/41] =?UTF-8?q?refactor=20:=20DefaultFarePolicy=20->=20D?= =?UTF-8?q?istanceFarePolicy=20=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...arePolicy.java => DistanceFarePolicy.java} | 2 +- .../policy/ChargePolicyCompositeTest.java | 158 +++++++++--------- .../policy/fare/DefaultFarePolicyTest.java | 96 ----------- .../policy/fare/DistanceFarePolicyTest.java | 95 +++++++++++ 4 files changed, 172 insertions(+), 179 deletions(-) rename src/main/java/subway/domain/policy/fare/{DefaultFarePolicy.java => DistanceFarePolicy.java} (96%) delete mode 100644 src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java create mode 100644 src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java diff --git a/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java similarity index 96% rename from src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java rename to src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java index 2b4d6b2d9..9f38468b6 100644 --- a/src/main/java/subway/domain/policy/fare/DefaultFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java @@ -10,7 +10,7 @@ import subway.domain.route.Route; @Component -public class DefaultFarePolicy implements SubwayFarePolicy { +public class DistanceFarePolicy implements SubwayFarePolicy { private static final Money DEFAULT_PRICE = new Money(1250); private static final BigDecimal ADDITIONAL_FEE = BigDecimal.valueOf(100); diff --git a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java index bf665dce0..407a5be86 100644 --- a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java @@ -1,5 +1,8 @@ package subway.domain.policy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -7,94 +10,85 @@ import subway.domain.line.Line; import subway.domain.policy.discount.AgeDiscountPolicy; import subway.domain.policy.discount.DiscountCondition; -import subway.domain.policy.fare.DefaultFarePolicy; +import subway.domain.policy.fare.DistanceFarePolicy; import subway.domain.policy.fare.LineFarePolicy; import subway.domain.route.Route; import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - class ChargePolicyCompositeTest { - private ChargePolicyComposite pricePolicyComposite; - - @BeforeEach - void setUp() { - pricePolicyComposite = new ChargePolicyComposite( - List.of(new DefaultFarePolicy(), - new LineFarePolicy()), - List.of(new AgeDiscountPolicy()) - ); - } - - /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | - * A -- B -- C -- D - * 1 2 3 - */ - @Test - @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") - void test_calculate() throws Exception { - //given - final List lines = createDefaultLines(); - final Route route = new Route( - lines, - new Station("A"), - new Station("G") - ); - - //when - final Money totalMoney = pricePolicyComposite.calculate(route); - - //then - assertEquals(new Money(2350), totalMoney); - } - - @Test - @DisplayName("discount() : 모든 할인 요금 정책을 계산할 수 있다.") - void test_discount() throws Exception { - //given - final DiscountCondition discountCondition = new DiscountCondition(14); - final Money money = new Money(10350); - - //when - final Money discountedMoney = pricePolicyComposite.discount(discountCondition, money); - - //then - assertEquals(new Money(8000), discountedMoney); - } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } + private ChargePolicyComposite pricePolicyComposite; + + @BeforeEach + void setUp() { + pricePolicyComposite = new ChargePolicyComposite( + List.of(new DistanceFarePolicy(), + new LineFarePolicy()), + List.of(new AgeDiscountPolicy()) + ); + } + + /** + * 11 5 F -- G -- H 4 | | 4 | | A -- B -- C -- D 1 2 3 + */ + @Test + @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") + void test_calculate() throws Exception { + //given + final List lines = createDefaultLines(); + final Route route = new Route( + lines, + new Station("A"), + new Station("G") + ); + + //when + final Money totalMoney = pricePolicyComposite.calculate(route); + + //then + assertEquals(new Money(2350), totalMoney); + } + + @Test + @DisplayName("discount() : 모든 할인 요금 정책을 계산할 수 있다.") + void test_discount() throws Exception { + //given + final DiscountCondition discountCondition = new DiscountCondition(14); + final Money money = new Money(10350); + + //when + final Money discountedMoney = pricePolicyComposite.discount(discountCondition, money); + + //then + assertEquals(new Money(8000), discountedMoney); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } } diff --git a/src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java b/src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java deleted file mode 100644 index df22479e8..000000000 --- a/src/test/java/subway/domain/policy/fare/DefaultFarePolicyTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package subway.domain.policy.fare; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.route.Route; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; - -import java.util.List; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class DefaultFarePolicyTest { - - private SubwayFarePolicy subwayFarePolicy; - - @BeforeEach - void setUp() { - subwayFarePolicy = new DefaultFarePolicy(); - } - - @ParameterizedTest - @MethodSource("calculatePriceFromDistance") - @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") - void test_calculate(final Station from, final Station to, final Money price) throws Exception { - //given - final List lines = createDefaultLines(); - final Route route = new Route(lines, from, to); - - //when - final Money result = subwayFarePolicy.calculate(route); - - //then - assertEquals(result, price); - } - - static Stream calculatePriceFromDistance() { - - final Station start1 = new Station("A"); - final Station end1 = new Station("G"); - final Money money1 = new Money(1350); - - final Station start2 = new Station("A"); - final Station end2 = new Station("H"); - final Money money2 = new Money(1250); - - final Station start3 = new Station("G"); - final Station end3 = new Station("C"); - final Money money3 = new Money(1350); - - final Station start4 = new Station("F"); - final Station end4 = new Station("H"); - final Money money4 = new Money(1350); - - return Stream.of( - Arguments.of(start1, end1, money1), - Arguments.of(start2, end2, money2), - Arguments.of(start3, end3, money3), - Arguments.of(start4, end4, money4) - ); - } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } -} diff --git a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java new file mode 100644 index 000000000..6e3672b24 --- /dev/null +++ b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java @@ -0,0 +1,95 @@ +package subway.domain.policy.fare; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import subway.domain.Money; +import subway.domain.line.Line; +import subway.domain.route.Route; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; + +class DistanceFarePolicyTest { + + private SubwayFarePolicy subwayFarePolicy; + + @BeforeEach + void setUp() { + subwayFarePolicy = new DistanceFarePolicy(); + } + + @ParameterizedTest + @MethodSource("calculatePriceFromDistance") + @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") + void test_calculate(final Station from, final Station to, final Money price) throws Exception { + //given + final List lines = createDefaultLines(); + final Route route = new Route(lines, from, to); + + //when + final Money result = subwayFarePolicy.calculate(route); + + //then + assertEquals(result, price); + } + + static Stream calculatePriceFromDistance() { + + final Station start1 = new Station("A"); + final Station end1 = new Station("G"); + final Money money1 = new Money(1350); + + final Station start2 = new Station("A"); + final Station end2 = new Station("H"); + final Money money2 = new Money(1250); + + final Station start3 = new Station("G"); + final Station end3 = new Station("C"); + final Money money3 = new Money(1350); + + final Station start4 = new Station("F"); + final Station end4 = new Station("H"); + final Money money4 = new Money(1350); + + return Stream.of( + Arguments.of(start1, end1, money1), + Arguments.of(start2, end2, money2), + Arguments.of(start3, end3, money3), + Arguments.of(start4, end4, money4) + ); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } +} From d320f8513009950588213f58e15305514ba969cc Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 09:04:17 +0900 Subject: [PATCH 33/41] =?UTF-8?q?refactor=20:=20Route=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JgraphtRouteFinder를 빈으로 등록 --- .../domain/policy/ChargePolicyComposite.java | 20 +- .../policy/fare/DistanceFarePolicy.java | 15 +- .../domain/policy/fare/LineFarePolicy.java | 12 +- .../domain/policy/fare/SubwayFarePolicy.java | 4 +- .../domain/route/JgraphtRouteFinder.java | 20 +- src/main/java/subway/domain/route/Route.java | 35 --- .../subway/service/RouteQueryService.java | 43 ++-- .../policy/ChargePolicyCompositeTest.java | 59 ++--- .../policy/fare/DistanceFarePolicyTest.java | 81 +++---- .../java/subway/domain/route/RouteTest.java | 217 ------------------ 10 files changed, 112 insertions(+), 394 deletions(-) delete mode 100644 src/main/java/subway/domain/route/Route.java delete mode 100644 src/test/java/subway/domain/route/RouteTest.java diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java index aa290489b..1e5ac196e 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -7,7 +7,7 @@ import subway.domain.policy.discount.DiscountCondition; import subway.domain.policy.discount.SubwayDiscountPolicy; import subway.domain.policy.fare.SubwayFarePolicy; -import subway.domain.route.Route; +import subway.domain.route.RouteFinder; @Primary @Component @@ -24,13 +24,6 @@ public ChargePolicyComposite( this.discountPolicies = discountPolicies; } - @Override - public Money calculate(final Route route) { - return farePolicies.stream() - .map(it -> it.calculate(route)) - .reduce(Money.ZERO, Money::add); - } - @Override public Money discount(final DiscountCondition discountCondition, final Money price) { return discountPolicies.stream() @@ -38,4 +31,15 @@ public Money discount(final DiscountCondition discountCondition, final Money pri subwayDiscountPolicy.discount(discountCondition, money), (money1, money2) -> money2); } + + @Override + public Money calculate( + final RouteFinder routeFinder, + final String departure, + final String arrival + ) { + return farePolicies.stream() + .map(it -> it.calculate(routeFinder, departure, arrival)) + .reduce(Money.ZERO, Money::add); + } } diff --git a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java index 9f38468b6..3310bd37b 100644 --- a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; import subway.domain.Distance; import subway.domain.Money; -import subway.domain.route.Route; +import subway.domain.route.RouteFinder; @Component public class DistanceFarePolicy implements SubwayFarePolicy { @@ -18,20 +18,21 @@ public class DistanceFarePolicy implements SubwayFarePolicy { private static final int LONG_DISTANCE_RATE = 8; @Override - public Money calculate(final Route route) { - final Distance distanceValue = route.findShortestRouteDistance(); + public Money calculate(final RouteFinder routeFinder, final String departure, + final String arrival) { + final Distance distance = routeFinder.findShortestRouteDistance(departure, arrival); - if (distanceValue.isDefaultDistance()) { + if (distance.isDefaultDistance()) { return DEFAULT_PRICE; } - if (distanceValue.isLongDistance()) { + if (distance.isLongDistance()) { return DEFAULT_PRICE.add(calculateMidDistance(MID_DISTANCE)) - .add(calculateLongDistance(distanceValue.minus(MID_DISTANCE) + .add(calculateLongDistance(distance.minus(MID_DISTANCE) .minus(DEFAULT_DISTANCE))); } - return DEFAULT_PRICE.add(calculateMidDistance(distanceValue.minus(DEFAULT_DISTANCE))); + return DEFAULT_PRICE.add(calculateMidDistance(distance.minus(DEFAULT_DISTANCE))); } private BigDecimal calculateMidDistance(final Distance distance) { diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java index 6f377411f..c9f506a0d 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -5,7 +5,7 @@ import org.springframework.stereotype.Component; import subway.domain.Money; import subway.domain.route.EdgeSection; -import subway.domain.route.Route; +import subway.domain.route.RouteFinder; @Component public class LineFarePolicy implements SubwayFarePolicy { @@ -15,9 +15,13 @@ public class LineFarePolicy implements SubwayFarePolicy { "2호선", 1000); @Override - public Money calculate(final Route route) { - - final List shortestRouteSections = route.findShortestRouteSections(); + public Money calculate( + final RouteFinder routeFinder, + final String departure, + final String arrival + ) { + final List shortestRouteSections = routeFinder.findShortestRouteSections(departure, + arrival); return shortestRouteSections.stream() .reduce(Money.ZERO, (money, edgeSection) -> diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java index 50c579fc3..5aed4b363 100644 --- a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java @@ -1,9 +1,9 @@ package subway.domain.policy.fare; import subway.domain.Money; -import subway.domain.route.Route; +import subway.domain.route.RouteFinder; public interface SubwayFarePolicy { - Money calculate(final Route route); + Money calculate(final RouteFinder routeFinder, final String departure, final String arrival); } diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java index 0d1389334..370adbd78 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -4,21 +4,33 @@ import org.jgrapht.Graph; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.WeightedMultigraph; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; import subway.domain.Distance; import subway.domain.line.Line; import subway.domain.section.Section; import subway.domain.station.Stations; +import subway.service.LineQueryService; +@Component public class JgraphtRouteFinder implements RouteFinder { - private final DijkstraShortestPath dijkstraGraph; + private DijkstraShortestPath dijkstraGraph; + private final LineQueryService lineQueryService; + + public JgraphtRouteFinder(final LineQueryService lineQueryService) { + this.lineQueryService = lineQueryService; + } + + @EventListener(ContextRefreshedEvent.class) + public void init() { + final List lines = lineQueryService.searchAllLine(); - public JgraphtRouteFinder(final List lines) { Graph graph = new WeightedMultigraph<>(EdgeSection.class); for (final Line line : lines) { - final List
sections = line.getSections(); makeGraphFromSections(graph, line); } @@ -67,6 +79,8 @@ private void addEdge( graph.setEdgeWeight(end, distance); } + //TODO : 역 연산 수행될 때마다 update + @Override public List findShortestRoute(final String startStation, final String endStation) { return dijkstraGraph.getPath(startStation, endStation).getVertexList(); diff --git a/src/main/java/subway/domain/route/Route.java b/src/main/java/subway/domain/route/Route.java deleted file mode 100644 index 12470e0fc..000000000 --- a/src/main/java/subway/domain/route/Route.java +++ /dev/null @@ -1,35 +0,0 @@ -package subway.domain.route; - -import java.util.List; -import subway.domain.Distance; -import subway.domain.line.Line; -import subway.domain.station.Station; - -public class Route { - - private final RouteFinder routeFinder; - private final Station from; - private final Station to; - - public Route( - final List lines, - final Station from, - final Station to - ) { - this.routeFinder = new JgraphtRouteFinder(lines); - this.from = from; - this.to = to; - } - - public List findShortestRoute() { - return routeFinder.findShortestRoute(from.getName(), to.getName()); - } - - public Distance findShortestRouteDistance() { - return routeFinder.findShortestRouteDistance(from.getName(), to.getName()); - } - - public List findShortestRouteSections() { - return routeFinder.findShortestRouteSections(from.getName(), to.getName()); - } -} diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 69dbffb47..32247970e 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,15 +1,11 @@ package subway.service; -import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.domain.Distance; import subway.domain.Money; -import subway.domain.line.Line; import subway.domain.policy.ChargePolicyComposite; import subway.domain.policy.discount.DiscountCondition; -import subway.domain.route.Route; -import subway.domain.station.Station; +import subway.domain.route.RouteFinder; import subway.service.dto.ShortestRouteRequest; import subway.service.dto.ShortestRouteResponse; @@ -17,43 +13,34 @@ @Transactional(readOnly = true) public class RouteQueryService { - private final LineQueryService lineQueryService; - private final ChargePolicyComposite chargePolicyComposite; + private final ChargePolicyComposite chargePolicyComposite2; + private final RouteFinder routeFinder; public RouteQueryService( - final LineQueryService lineQueryService, - final ChargePolicyComposite chargePolicyComposite + final ChargePolicyComposite chargePolicyComposite2, + final RouteFinder routeFinder ) { - this.lineQueryService = lineQueryService; - this.chargePolicyComposite = chargePolicyComposite; + this.chargePolicyComposite2 = chargePolicyComposite2; + this.routeFinder = routeFinder; } public ShortestRouteResponse searchShortestRoute( final ShortestRouteRequest shortestRouteRequest ) { - final List lines = lineQueryService.searchAllLine(); - - final Route route = new Route( - lines, - new Station(shortestRouteRequest.getStartStation()), - new Station(shortestRouteRequest.getEndStation()) - ); + final String departure = shortestRouteRequest.getStartStation(); + final String arrival = shortestRouteRequest.getEndStation(); return new ShortestRouteResponse( - route.findShortestRoute(), - searchCost(route, shortestRouteRequest.getAge()).getValue(), - searchShortestDistance(route).getValue() + routeFinder.findShortestRoute(departure, arrival), + searchCost(departure, arrival, shortestRouteRequest.getAge()).getValue(), + routeFinder.findShortestRouteDistance(departure, arrival).getValue() ); } - private Money searchCost(final Route route, final Integer age) { - final Money totalPrice = chargePolicyComposite.calculate(route); - - return chargePolicyComposite.discount(new DiscountCondition(age), totalPrice); - } + private Money searchCost(final String departure, final String arrival, final Integer age) { + final Money totalPrice = chargePolicyComposite2.calculate(routeFinder, departure, arrival); - private Distance searchShortestDistance(final Route route) { - return route.findShortestRouteDistance(); + return chargePolicyComposite2.discount(new DiscountCondition(age), totalPrice); } } diff --git a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java index 407a5be86..81c14fb45 100644 --- a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java @@ -6,21 +6,24 @@ 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.boot.test.context.SpringBootTest; import subway.domain.Money; -import subway.domain.line.Line; import subway.domain.policy.discount.AgeDiscountPolicy; import subway.domain.policy.discount.DiscountCondition; import subway.domain.policy.fare.DistanceFarePolicy; import subway.domain.policy.fare.LineFarePolicy; -import subway.domain.route.Route; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; +import subway.domain.route.RouteFinder; +@SpringBootTest class ChargePolicyCompositeTest { + @Autowired private ChargePolicyComposite pricePolicyComposite; + @Autowired + private RouteFinder routeFinder; + @BeforeEach void setUp() { pricePolicyComposite = new ChargePolicyComposite( @@ -31,21 +34,24 @@ void setUp() { } /** - * 11 5 F -- G -- H 4 | | 4 | | A -- B -- C -- D 1 2 3 + * + * 11 5 + * F - G - H + * 4 | | 2 + * | | + * A - B - C - D + * 1 2 3 */ + @Test @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") void test_calculate() throws Exception { //given - final List lines = createDefaultLines(); - final Route route = new Route( - lines, - new Station("A"), - new Station("G") - ); + final String departure = "A"; + final String arrival = "G"; //when - final Money totalMoney = pricePolicyComposite.calculate(route); + final Money totalMoney = pricePolicyComposite.calculate(routeFinder, departure, arrival); //then assertEquals(new Money(2350), totalMoney); @@ -64,31 +70,4 @@ void test_discount() throws Exception { //then assertEquals(new Money(8000), discountedMoney); } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } } diff --git a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java index 6e3672b24..0f51c8ade 100644 --- a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java +++ b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java @@ -1,40 +1,44 @@ package subway.domain.policy.fare; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import subway.domain.Distance; import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.route.Route; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; +import subway.domain.route.RouteFinder; class DistanceFarePolicyTest { private SubwayFarePolicy subwayFarePolicy; + private RouteFinder routeFinder; + @BeforeEach void setUp() { + routeFinder = mock(RouteFinder.class); + subwayFarePolicy = new DistanceFarePolicy(); } @ParameterizedTest @MethodSource("calculatePriceFromDistance") @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") - void test_calculate(final Station from, final Station to, final Money price) throws Exception { + void test_calculate(final String departure, final String arrival, final Money price, + final Distance distance) throws Exception { //given - final List lines = createDefaultLines(); - final Route route = new Route(lines, from, to); + when(routeFinder.findShortestRouteDistance(any(), any())) + .thenReturn(distance); //when - final Money result = subwayFarePolicy.calculate(route); + final Money result = subwayFarePolicy.calculate(routeFinder, departure, arrival); //then assertEquals(result, price); @@ -42,54 +46,31 @@ void test_calculate(final Station from, final Station to, final Money price) thr static Stream calculatePriceFromDistance() { - final Station start1 = new Station("A"); - final Station end1 = new Station("G"); + final String start1 = "A"; + final String end1 = "G"; final Money money1 = new Money(1350); + final Distance distance1 = new Distance(13); - final Station start2 = new Station("A"); - final Station end2 = new Station("H"); + final String start2 = "A"; + final String end2 = "H"; final Money money2 = new Money(1250); + final Distance distance2 = new Distance(8); - final Station start3 = new Station("G"); - final Station end3 = new Station("C"); - final Money money3 = new Money(1350); + final String start3 = "G"; + final String end3 = "C"; + final Money money3 = new Money(1250); + final Distance distance3 = new Distance(10); - final Station start4 = new Station("F"); - final Station end4 = new Station("H"); + final String start4 = "F"; + final String end4 = "H"; final Money money4 = new Money(1350); + final Distance distance4 = new Distance(11); return Stream.of( - Arguments.of(start1, end1, money1), - Arguments.of(start2, end2, money2), - Arguments.of(start3, end3, money3), - Arguments.of(start4, end4, money4) + Arguments.of(start1, end1, money1, distance1), + Arguments.of(start2, end2, money2, distance2), + Arguments.of(start3, end3, money3, distance3), + Arguments.of(start4, end4, money4, distance4) ); } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } } diff --git a/src/test/java/subway/domain/route/RouteTest.java b/src/test/java/subway/domain/route/RouteTest.java deleted file mode 100644 index d28fd1e39..000000000 --- a/src/test/java/subway/domain/route/RouteTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package subway.domain.route; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import subway.domain.Distance; -import subway.domain.line.Line; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - - -class RouteTest { - - /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | - * A -- B -- C -- D - * 1 2 3 - */ - - @ParameterizedTest - @MethodSource("findShortestRoute") - @DisplayName("findShortestRoute() : 시작점과 도착점이 주어지면 최단 경로를 구할 수 있다.") - void test_findShortestRoute( - final String start, - final String end, - final List routes - ) throws Exception { - //given - final List lines = createDefaultLines(); - final Route route = new Route(lines, new Station(start), new Station(end)); - - //when - final List shortestRoute = route.findShortestRoute(); - - //then - assertThat(shortestRoute).containsExactlyElementsOf(routes); - } - - static Stream findShortestRoute() { - - final String start1 = "A"; - final String end1 = "G"; - final List route1 = List.of("A", "B", "C", "D", "H", "G"); - - final String start2 = "A"; - final String end2 = "H"; - final List route2 = List.of("A", "B", "C", "D", "H"); - - final String start3 = "G"; - final String end3 = "C"; - final List route3 = List.of("G", "H", "D", "C"); - - final String start4 = "F"; - final String end4 = "H"; - final List route4 = List.of("F", "B", "C", "D", "H"); - - return Stream.of( - Arguments.of(start1, end1, route1), - Arguments.of(start2, end2, route2), - Arguments.of(start3, end3, route3), - Arguments.of(start4, end4, route4) - ); - } - - /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | - * A -- B -- C -- D - * 1 2 3 - */ - @ParameterizedTest - @MethodSource("findShortestRouteDistance") - @DisplayName("findShortestRouteDistance() : 시작점과 도착점이 주어지면 최단 거리를 구할 수 있다.") - void test_findShortestRoutePrice( - final Station start, - final Station end, - final double distance - ) throws Exception { - - //given - final List lines = createDefaultLines(); - final Route route = new Route(lines, start, end); - - //when - final Distance shortestRouteDistance = route.findShortestRouteDistance(); - - //then - assertEquals(distance, shortestRouteDistance.getValue()); - } - - static Stream findShortestRouteDistance() { - - final Station start1 = new Station("A"); - final Station end1 = new Station("G"); - final double distance1 = 15.0; - - final Station start2 = new Station("A"); - final Station end2 = new Station("H"); - final double distance2 = 10.0; - - final Station start3 = new Station("G"); - final Station end3 = new Station("C"); - final double distance3 = 12.0; - - final Station start4 = new Station("F"); - final Station end4 = new Station("H"); - final double distance4 = 13.0; - - return Stream.of( - Arguments.of(start1, end1, distance1), - Arguments.of(start2, end2, distance2), - Arguments.of(start3, end3, distance3), - Arguments.of(start4, end4, distance4) - ); - } - - @Test - @DisplayName("findShortestRoute() : 도착점이나 출발점이 하나라도 그래프에 없다면 IllegalArgumentException이 발생한다.") - void test_findShortestRoute_IllegalArgumentException_notContainStartOrEnd() throws Exception { - //given - final List lines = createDefaultLines(); - final Station from = new Station("A"); - final Station notExistTo = new Station("K"); - - final Route route = new Route(lines, from, notExistTo); - - //when & then - assertThatThrownBy(route::findShortestRoute) - .isInstanceOf(IllegalArgumentException.class); - } - - /** - * 11 5 - * F -- G -- H - * 4 | | 4 - * | | - * A -- B -- C -- D - * 1 2 3 - */ - - @Test - @DisplayName("findShortestRouteSections() : 최단 경로에 속한 섹션들을 구할 수 있다.") - void test_findShortestRouteSections() throws Exception { - //given - final List lines = createDefaultLines(); - final Station from = new Station("A"); - final Station to = new Station("G"); - - final Route route = new Route(lines, from, to); - - //when - final List shortestRouteSections = route.findShortestRouteSections(); - - //then - final List startStations = - shortestRouteSections.stream() - .map(EdgeSection::getStartStation) - .collect(Collectors.toList()); - - final List endStations = - shortestRouteSections.stream() - .map(EdgeSection::getEndStation) - .collect(Collectors.toList()); - - assertAll( - () -> assertEquals(5, shortestRouteSections.size()), - () -> assertThat(startStations).containsAnyElementsOf( - List.of("A", "B", "C", "D", "H")), - () -> assertThat(endStations).containsAnyElementsOf( - List.of("B", "C", "D", "H", "G")) - ); - } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } -} From c9ee77473645013bb42a3c6fcce252246c18e768 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 09:20:44 +0900 Subject: [PATCH 34/41] =?UTF-8?q?feat=20:=20=EC=B2=98=EC=9D=8C=20=EC=95=A0?= =?UTF-8?q?=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=EC=9D=B4=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=EB=90=A0=20=EB=95=8C=EC=99=80=20=EC=97=AD?= =?UTF-8?q?=EC=97=90=20=EB=B3=80=EA=B2=BD=EC=9D=B4=20=EC=9D=BC=EC=96=B4?= =?UTF-8?q?=EB=82=A0=20=EA=B2=BD=EC=9A=B0=20=EB=8B=A4=EC=9D=B5=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=9D=BC=20=EA=B7=B8=EB=9E=98=ED=94=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=98=EB=8A=94=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/route/JgraphtRouteFinder.java | 7 ++-- src/main/java/subway/event/StationChange.java | 4 +++ .../java/subway/service/StationService.java | 12 +++++-- .../domain/route/JgraphtRouteFinderTest.java | 32 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 src/main/java/subway/event/StationChange.java create mode 100644 src/test/java/subway/domain/route/JgraphtRouteFinderTest.java diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java index 370adbd78..246616d36 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -11,6 +11,7 @@ import subway.domain.line.Line; import subway.domain.section.Section; import subway.domain.station.Stations; +import subway.event.StationChange; import subway.service.LineQueryService; @Component @@ -23,8 +24,8 @@ public JgraphtRouteFinder(final LineQueryService lineQueryService) { this.lineQueryService = lineQueryService; } - @EventListener(ContextRefreshedEvent.class) - public void init() { + @EventListener({ContextRefreshedEvent.class, StationChange.class}) + public void updateDijkstraGraph() { final List lines = lineQueryService.searchAllLine(); Graph graph @@ -79,8 +80,6 @@ private void addEdge( graph.setEdgeWeight(end, distance); } - //TODO : 역 연산 수행될 때마다 update - @Override public List findShortestRoute(final String startStation, final String endStation) { return dijkstraGraph.getPath(startStation, endStation).getVertexList(); diff --git a/src/main/java/subway/event/StationChange.java b/src/main/java/subway/event/StationChange.java new file mode 100644 index 000000000..afd144188 --- /dev/null +++ b/src/main/java/subway/event/StationChange.java @@ -0,0 +1,4 @@ +package subway.event; + +public class StationChange { +} diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java index 545431fc4..fed84613b 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/service/StationService.java @@ -3,12 +3,14 @@ import java.util.List; import java.util.Objects; import java.util.function.Consumer; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.line.Line; import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; +import subway.event.StationChange; import subway.service.dto.StationDeleteRequest; import subway.service.dto.StationRegisterRequest; @@ -19,15 +21,17 @@ public class StationService { private final SectionCommandService sectionCommandService; private final LineCommandService lineCommandService; private final LineQueryService lineQueryService; + private final ApplicationEventPublisher applicationEventPublisher; public StationService( final SectionCommandService sectionCommandService, final LineCommandService lineCommandService, - final LineQueryService lineQueryService - ) { + final LineQueryService lineQueryService, + final ApplicationEventPublisher applicationEventPublisher) { this.sectionCommandService = sectionCommandService; this.lineCommandService = lineCommandService; this.lineQueryService = lineQueryService; + this.applicationEventPublisher = applicationEventPublisher; } public void registerStation(final StationRegisterRequest stationRegisterRequest) { @@ -53,6 +57,8 @@ public void registerStation(final StationRegisterRequest stationRegisterRequest) .filter(section -> Objects.nonNull(section.getId())) .findFirst() .ifPresent(sectionCommandService::updateSection); + + applicationEventPublisher.publishEvent(new StationChange()); } private Section mapToSectionFrom(final StationRegisterRequest stationRegisterRequest) { @@ -88,6 +94,8 @@ public void deleteStation(final StationDeleteRequest stationDeleteRequest) { sectionCommandService.deleteAll(line.getId()); lineCommandService.deleteLine(line.getId()); } + + applicationEventPublisher.publishEvent(new StationChange()); } private Consumer
updateAndDeleteSection( diff --git a/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java b/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java new file mode 100644 index 000000000..ba4469f19 --- /dev/null +++ b/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java @@ -0,0 +1,32 @@ +package subway.domain.route; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationEventPublisher; +import subway.event.StationChange; + +@SpringBootTest +class JgraphtRouteFinderTest { + + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; + + @Test + @DisplayName("init() : 애플리케이션 컨테이너가 뜰 때와 역이 변경될 경우 이벤트가 실행될 수 있다.") + void test_init_eventListener() throws Exception { + //given + applicationEventPublisher.publishEvent(new StationChange()); + + //when & then + verify(jgraphtRouteFinder, times(2)).updateDijkstraGraph(); + } +} From 62caf140ec20d0584b9138abcf91edde3f6ccfdb Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 09:37:19 +0900 Subject: [PATCH 35/41] =?UTF-8?q?test=20:=20yml=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=8B=9C=20=EC=95=A0=ED=94=8C=EB=A6=AC=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=A4?= =?UTF-8?q?=EA=B0=80=20=EB=9D=84=EC=9B=8C=EC=A7=80=EB=A9=B4=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=B2=A4=ED=8A=B8?= =?UTF-8?q?=EA=B0=80=20=EC=88=98=ED=96=89=EB=90=98=EA=B8=B0=20=EB=95=8C?= =?UTF-8?q?=EB=AC=B8=EC=97=90=20=EC=9D=B4=EB=A5=BC=20=EB=B0=A9=EC=A7=80?= =?UTF-8?q?=ED=95=98=EA=B3=A0=EC=9E=90=20Profile=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20JgraphtRouteFinder=20=EB=A5=BC=20Mock?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/subway/yml/ProfileActiveFirstTest.java | 5 +++++ src/test/java/subway/yml/ProfileActiveSecondTest.java | 5 +++++ src/test/java/subway/yml/ProfileActiveThirdTest.java | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/test/java/subway/yml/ProfileActiveFirstTest.java b/src/test/java/subway/yml/ProfileActiveFirstTest.java index 3c918223c..e4f429a22 100644 --- a/src/test/java/subway/yml/ProfileActiveFirstTest.java +++ b/src/test/java/subway/yml/ProfileActiveFirstTest.java @@ -3,9 +3,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; +import subway.domain.route.JgraphtRouteFinder; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,6 +18,9 @@ public class ProfileActiveFirstTest { @Autowired private DataSource dataSource; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; + @Test void test_first() throws Exception { String expectedDatabaseUrl = "jdbc:h2:mem:first"; diff --git a/src/test/java/subway/yml/ProfileActiveSecondTest.java b/src/test/java/subway/yml/ProfileActiveSecondTest.java index db38b783f..326437e5d 100644 --- a/src/test/java/subway/yml/ProfileActiveSecondTest.java +++ b/src/test/java/subway/yml/ProfileActiveSecondTest.java @@ -3,9 +3,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; +import subway.domain.route.JgraphtRouteFinder; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,6 +18,9 @@ public class ProfileActiveSecondTest { @Autowired private DataSource dataSource; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; + @Test void test_default1() throws Exception { String expectedDatabaseUrl = "jdbc:h2:mem:second"; diff --git a/src/test/java/subway/yml/ProfileActiveThirdTest.java b/src/test/java/subway/yml/ProfileActiveThirdTest.java index a578257e2..3b2883cd8 100644 --- a/src/test/java/subway/yml/ProfileActiveThirdTest.java +++ b/src/test/java/subway/yml/ProfileActiveThirdTest.java @@ -3,9 +3,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; +import subway.domain.route.JgraphtRouteFinder; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -16,6 +18,9 @@ public class ProfileActiveThirdTest { @Autowired private DataSource dataSource; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; + @Test void test_third() throws Exception { String expectedDatabaseUrl = "jdbc:h2:mem:third"; From d3d66cb8fe28cf8e6ed181ed6e761a050ca559f4 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 09:53:08 +0900 Subject: [PATCH 36/41] =?UTF-8?q?refactor=20:=20Policy=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=B9=88=20=ED=95=B4=EC=A0=9C=ED=95=98=EA=B3=A0,?= =?UTF-8?q?=20Composite=20=EB=A7=8C=20=EB=B9=88=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/config/ChargePolicyConfig.java | 21 +++++++++++++++++++ .../domain/policy/ChargePolicyComposite.java | 4 ---- .../policy/discount/AgeDiscountPolicy.java | 2 -- .../policy/fare/DistanceFarePolicy.java | 2 -- .../domain/policy/fare/LineFarePolicy.java | 2 -- 5 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/main/java/subway/config/ChargePolicyConfig.java diff --git a/src/main/java/subway/config/ChargePolicyConfig.java b/src/main/java/subway/config/ChargePolicyConfig.java new file mode 100644 index 000000000..045825e60 --- /dev/null +++ b/src/main/java/subway/config/ChargePolicyConfig.java @@ -0,0 +1,21 @@ +package subway.config; + +import java.util.List; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import subway.domain.policy.ChargePolicyComposite; +import subway.domain.policy.discount.AgeDiscountPolicy; +import subway.domain.policy.fare.DistanceFarePolicy; +import subway.domain.policy.fare.LineFarePolicy; + +@Configuration +public class ChargePolicyConfig { + + @Bean + public ChargePolicyComposite chargePolicyComposite() { + return new ChargePolicyComposite( + List.of(new DistanceFarePolicy(), new LineFarePolicy()), + List.of(new AgeDiscountPolicy()) + ); + } +} diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java index 1e5ac196e..6d7b29ed2 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -1,16 +1,12 @@ package subway.domain.policy; import java.util.List; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; import subway.domain.Money; import subway.domain.policy.discount.DiscountCondition; import subway.domain.policy.discount.SubwayDiscountPolicy; import subway.domain.policy.fare.SubwayFarePolicy; import subway.domain.route.RouteFinder; -@Primary -@Component public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { private final List farePolicies; diff --git a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java index fca80d8e1..1e87049ee 100644 --- a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java +++ b/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java @@ -2,10 +2,8 @@ import java.util.EnumMap; import java.util.Map; -import org.springframework.stereotype.Component; import subway.domain.Money; -@Component public class AgeDiscountPolicy implements SubwayDiscountPolicy { private static final Map policyMap = new EnumMap<>(AgeGroup.class); diff --git a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java index 3310bd37b..febc9d18d 100644 --- a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java @@ -4,12 +4,10 @@ import static subway.domain.Distance.MID_DISTANCE; import java.math.BigDecimal; -import org.springframework.stereotype.Component; import subway.domain.Distance; import subway.domain.Money; import subway.domain.route.RouteFinder; -@Component public class DistanceFarePolicy implements SubwayFarePolicy { private static final Money DEFAULT_PRICE = new Money(1250); diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java index c9f506a0d..6a1d6f92c 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -2,12 +2,10 @@ import java.util.List; import java.util.Map; -import org.springframework.stereotype.Component; import subway.domain.Money; import subway.domain.route.EdgeSection; import subway.domain.route.RouteFinder; -@Component public class LineFarePolicy implements SubwayFarePolicy { private static final Map priceMap From 10b95bb735e2be4aeb36e9fd092300e0687de158 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 13:21:19 +0900 Subject: [PATCH 37/41] =?UTF-8?q?refactor=20:=20Line=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=8B=9C=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/service/LineCommandService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/subway/service/LineCommandService.java b/src/main/java/subway/service/LineCommandService.java index d5165c021..c3f74f9db 100644 --- a/src/main/java/subway/service/LineCommandService.java +++ b/src/main/java/subway/service/LineCommandService.java @@ -1,9 +1,11 @@ package subway.service; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.dao.LineDao; import subway.dao.LineEntity; +import subway.event.StationChange; import subway.exception.line.CanNotDuplicatedLineNameException; import subway.service.dto.RegisterLineRequest; @@ -14,15 +16,17 @@ public class LineCommandService { private final LineDao lineDao; private final SectionCommandService sectionCommandService; private final LineQueryService lineQueryService; + private final ApplicationEventPublisher applicationEventPublisher; public LineCommandService( final LineDao lineDao, final SectionCommandService sectionCommandService, - final LineQueryService lineQueryService - ) { + final LineQueryService lineQueryService, + final ApplicationEventPublisher applicationEventPublisher) { this.lineDao = lineDao; this.sectionCommandService = sectionCommandService; this.lineQueryService = lineQueryService; + this.applicationEventPublisher = applicationEventPublisher; } public void deleteLine(final Long lineId) { @@ -45,5 +49,7 @@ public void registerLine(final RegisterLineRequest registerLineRequest) { registerLineRequest.getDistance(), savedId ); + + applicationEventPublisher.publishEvent(new StationChange()); } } From 966df8416936a64ce35900757ecdbe19b88218cc Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 13:52:48 +0900 Subject: [PATCH 38/41] =?UTF-8?q?refactor=20:=20=EC=B5=9C=EC=86=8C=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EA=B5=AC=ED=95=A0=20=EB=95=8C,=20key=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=97=AD=20=EC=9D=B4=EB=A6=84(String)?= =?UTF-8?q?=EC=9D=B4=20=EC=95=84=EB=8B=8C=20Station=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/policy/ChargePolicyComposite.java | 5 +-- .../policy/fare/DistanceFarePolicy.java | 5 +-- .../domain/policy/fare/LineFarePolicy.java | 5 +-- .../domain/policy/fare/SubwayFarePolicy.java | 3 +- .../domain/route/JgraphtRouteFinder.java | 36 +++++++++---------- .../java/subway/domain/route/RouteFinder.java | 7 ++-- .../java/subway/domain/station/Station.java | 19 ++++++++++ .../subway/service/RouteQueryService.java | 30 ++++++++++------ .../policy/ChargePolicyCompositeTest.java | 5 +-- .../policy/fare/DistanceFarePolicyTest.java | 19 +++++----- 10 files changed, 84 insertions(+), 50 deletions(-) diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java index 6d7b29ed2..26c48b4bf 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -6,6 +6,7 @@ import subway.domain.policy.discount.SubwayDiscountPolicy; import subway.domain.policy.fare.SubwayFarePolicy; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { @@ -31,8 +32,8 @@ public Money discount(final DiscountCondition discountCondition, final Money pri @Override public Money calculate( final RouteFinder routeFinder, - final String departure, - final String arrival + final Station departure, + final Station arrival ) { return farePolicies.stream() .map(it -> it.calculate(routeFinder, departure, arrival)) diff --git a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java index febc9d18d..1c341442b 100644 --- a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java @@ -7,6 +7,7 @@ import subway.domain.Distance; import subway.domain.Money; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; public class DistanceFarePolicy implements SubwayFarePolicy { @@ -16,8 +17,8 @@ public class DistanceFarePolicy implements SubwayFarePolicy { private static final int LONG_DISTANCE_RATE = 8; @Override - public Money calculate(final RouteFinder routeFinder, final String departure, - final String arrival) { + public Money calculate(final RouteFinder routeFinder, final Station departure, + final Station arrival) { final Distance distance = routeFinder.findShortestRouteDistance(departure, arrival); if (distance.isDefaultDistance()) { diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java index 6a1d6f92c..c5605ef66 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -5,6 +5,7 @@ import subway.domain.Money; import subway.domain.route.EdgeSection; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; public class LineFarePolicy implements SubwayFarePolicy { @@ -15,8 +16,8 @@ public class LineFarePolicy implements SubwayFarePolicy { @Override public Money calculate( final RouteFinder routeFinder, - final String departure, - final String arrival + final Station departure, + final Station arrival ) { final List shortestRouteSections = routeFinder.findShortestRouteSections(departure, arrival); diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java index 5aed4b363..bfd348556 100644 --- a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java @@ -2,8 +2,9 @@ import subway.domain.Money; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; public interface SubwayFarePolicy { - Money calculate(final RouteFinder routeFinder, final String departure, final String arrival); + Money calculate(final RouteFinder routeFinder, final Station departure, final Station arrival); } diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java index 246616d36..ee3064c39 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -10,6 +10,7 @@ import subway.domain.Distance; import subway.domain.line.Line; import subway.domain.section.Section; +import subway.domain.station.Station; import subway.domain.station.Stations; import subway.event.StationChange; import subway.service.LineQueryService; @@ -17,7 +18,7 @@ @Component public class JgraphtRouteFinder implements RouteFinder { - private DijkstraShortestPath dijkstraGraph; + private DijkstraShortestPath dijkstraGraph; private final LineQueryService lineQueryService; public JgraphtRouteFinder(final LineQueryService lineQueryService) { @@ -28,7 +29,7 @@ public JgraphtRouteFinder(final LineQueryService lineQueryService) { public void updateDijkstraGraph() { final List lines = lineQueryService.searchAllLine(); - Graph graph + Graph graph = new WeightedMultigraph<>(EdgeSection.class); for (final Line line : lines) { @@ -39,7 +40,7 @@ public void updateDijkstraGraph() { } private void makeGraphFromSections( - final Graph graph, + final Graph graph, final Line line ) { @@ -58,41 +59,38 @@ private void makeGraphFromSections( } private void addVertex( - final Graph graph, + final Graph graph, final String startStation, final String endStation ) { - graph.addVertex(startStation); - graph.addVertex(endStation); + graph.addVertex(new Station(startStation)); + graph.addVertex(new Station(endStation)); } private void addEdge( - final Graph graph, final String startStation, + final Graph graph, final String startStation, final String endStation, final int distance, final String lineName ) { final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); - graph.addEdge(startStation, endStation, start); - graph.addEdge(endStation, startStation, end); + graph.addEdge(new Station(startStation), new Station(endStation), start); + graph.addEdge(new Station(endStation), new Station(startStation), end); graph.setEdgeWeight(start, distance); graph.setEdgeWeight(end, distance); } - @Override - public List findShortestRoute(final String startStation, final String endStation) { - return dijkstraGraph.getPath(startStation, endStation).getVertexList(); + public List findShortestRoute(final Station departure, final Station arrival) { + return dijkstraGraph.getPath(departure, arrival).getVertexList(); } - @Override - public Distance findShortestRouteDistance(final String startStation, final String endStation) { - return new Distance((int) dijkstraGraph.getPathWeight(startStation, endStation)); + public Distance findShortestRouteDistance(final Station departure, final Station arrival) { + return new Distance((int) dijkstraGraph.getPathWeight(departure, arrival)); } - @Override - public List findShortestRouteSections(final String startStation, - final String endStation) { - return dijkstraGraph.getPath(startStation, endStation).getEdgeList(); + public List findShortestRouteSections(final Station departure, + final Station arrival) { + return dijkstraGraph.getPath(departure, arrival).getEdgeList(); } } diff --git a/src/main/java/subway/domain/route/RouteFinder.java b/src/main/java/subway/domain/route/RouteFinder.java index b90f1be03..3bbfca55c 100644 --- a/src/main/java/subway/domain/route/RouteFinder.java +++ b/src/main/java/subway/domain/route/RouteFinder.java @@ -2,12 +2,13 @@ import java.util.List; import subway.domain.Distance; +import subway.domain.station.Station; public interface RouteFinder { - List findShortestRoute(final String startStation, final String endStation); + List findShortestRoute(final Station departure, final Station arrival); - Distance findShortestRouteDistance(final String startStation, final String endStation); + Distance findShortestRouteDistance(final Station departure, final Station arrival); - List findShortestRouteSections(final String startStation, final String endStation); + List findShortestRouteSections(final Station departure, final Station arrival); } diff --git a/src/main/java/subway/domain/station/Station.java b/src/main/java/subway/domain/station/Station.java index ed414b57e..515399b02 100644 --- a/src/main/java/subway/domain/station/Station.java +++ b/src/main/java/subway/domain/station/Station.java @@ -1,5 +1,7 @@ package subway.domain.station; +import java.util.Objects; + public class Station { private String name; @@ -23,4 +25,21 @@ public Station cloneStation() { public String getName() { return name; } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Station station = (Station) o; + return Objects.equals(name, station.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 32247970e..10ef50a8b 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -1,11 +1,14 @@ package subway.service; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.Money; import subway.domain.policy.ChargePolicyComposite; import subway.domain.policy.discount.DiscountCondition; -import subway.domain.route.RouteFinder; +import subway.domain.route.JgraphtRouteFinder; +import subway.domain.station.Station; import subway.service.dto.ShortestRouteRequest; import subway.service.dto.ShortestRouteResponse; @@ -14,32 +17,39 @@ public class RouteQueryService { private final ChargePolicyComposite chargePolicyComposite2; - private final RouteFinder routeFinder; + private final JgraphtRouteFinder jgraphtRouteFinder; public RouteQueryService( final ChargePolicyComposite chargePolicyComposite2, - final RouteFinder routeFinder + final JgraphtRouteFinder jgraphtRouteFinder ) { this.chargePolicyComposite2 = chargePolicyComposite2; - this.routeFinder = routeFinder; + this.jgraphtRouteFinder = jgraphtRouteFinder; } public ShortestRouteResponse searchShortestRoute( final ShortestRouteRequest shortestRouteRequest ) { - final String departure = shortestRouteRequest.getStartStation(); - final String arrival = shortestRouteRequest.getEndStation(); + final Station departure = new Station(shortestRouteRequest.getStartStation()); + final Station arrival = new Station(shortestRouteRequest.getEndStation()); return new ShortestRouteResponse( - routeFinder.findShortestRoute(departure, arrival), + mapToStationNameFrom(jgraphtRouteFinder.findShortestRoute(departure, arrival)), searchCost(departure, arrival, shortestRouteRequest.getAge()).getValue(), - routeFinder.findShortestRouteDistance(departure, arrival).getValue() + jgraphtRouteFinder.findShortestRouteDistance(departure, arrival).getValue() ); } - private Money searchCost(final String departure, final String arrival, final Integer age) { - final Money totalPrice = chargePolicyComposite2.calculate(routeFinder, departure, arrival); + private List mapToStationNameFrom(final List stations) { + return stations.stream() + .map(Station::getName) + .collect(Collectors.toList()); + } + + private Money searchCost(final Station departure, final Station arrival, final Integer age) { + final Money totalPrice = chargePolicyComposite2.calculate(jgraphtRouteFinder, departure, + arrival); return chargePolicyComposite2.discount(new DiscountCondition(age), totalPrice); } diff --git a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java index 81c14fb45..ef1a7ba69 100644 --- a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java @@ -14,6 +14,7 @@ import subway.domain.policy.fare.DistanceFarePolicy; import subway.domain.policy.fare.LineFarePolicy; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; @SpringBootTest class ChargePolicyCompositeTest { @@ -47,8 +48,8 @@ void setUp() { @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") void test_calculate() throws Exception { //given - final String departure = "A"; - final String arrival = "G"; + final Station departure = new Station("A"); + final Station arrival = new Station("G"); //when final Money totalMoney = pricePolicyComposite.calculate(routeFinder, departure, arrival); diff --git a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java index 0f51c8ade..42c7e9c63 100644 --- a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java +++ b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java @@ -14,6 +14,7 @@ import subway.domain.Distance; import subway.domain.Money; import subway.domain.route.RouteFinder; +import subway.domain.station.Station; class DistanceFarePolicyTest { @@ -31,7 +32,7 @@ void setUp() { @ParameterizedTest @MethodSource("calculatePriceFromDistance") @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") - void test_calculate(final String departure, final String arrival, final Money price, + void test_calculate(final Station departure, final Station arrival, final Money price, final Distance distance) throws Exception { //given when(routeFinder.findShortestRouteDistance(any(), any())) @@ -46,23 +47,23 @@ void test_calculate(final String departure, final String arrival, final Money pr static Stream calculatePriceFromDistance() { - final String start1 = "A"; - final String end1 = "G"; + final Station start1 = new Station("A"); + final Station end1 = new Station("G"); final Money money1 = new Money(1350); final Distance distance1 = new Distance(13); - final String start2 = "A"; - final String end2 = "H"; + final Station start2 = new Station("A"); + final Station end2 = new Station("H"); final Money money2 = new Money(1250); final Distance distance2 = new Distance(8); - final String start3 = "G"; - final String end3 = "C"; + final Station start3 = new Station("G"); + final Station end3 = new Station("C"); final Money money3 = new Money(1250); final Distance distance3 = new Distance(10); - final String start4 = "F"; - final String end4 = "H"; + final Station start4 = new Station("F"); + final Station end4 = new Station("H"); final Money money4 = new Money(1350); final Distance distance4 = new Distance(11); From c6984bba1b8d97b777bce65df6c164628484528f Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 18:14:30 +0900 Subject: [PATCH 39/41] =?UTF-8?q?refactor=20:=20Event=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/subway/event/StationChange.java | 4 ---- src/main/java/subway/service/LineCommandService.java | 9 +-------- src/main/java/subway/service/StationService.java | 11 +---------- 3 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/subway/event/StationChange.java diff --git a/src/main/java/subway/event/StationChange.java b/src/main/java/subway/event/StationChange.java deleted file mode 100644 index afd144188..000000000 --- a/src/main/java/subway/event/StationChange.java +++ /dev/null @@ -1,4 +0,0 @@ -package subway.event; - -public class StationChange { -} diff --git a/src/main/java/subway/service/LineCommandService.java b/src/main/java/subway/service/LineCommandService.java index c3f74f9db..d2abd8afe 100644 --- a/src/main/java/subway/service/LineCommandService.java +++ b/src/main/java/subway/service/LineCommandService.java @@ -1,11 +1,9 @@ package subway.service; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.dao.LineDao; import subway.dao.LineEntity; -import subway.event.StationChange; import subway.exception.line.CanNotDuplicatedLineNameException; import subway.service.dto.RegisterLineRequest; @@ -16,17 +14,14 @@ public class LineCommandService { private final LineDao lineDao; private final SectionCommandService sectionCommandService; private final LineQueryService lineQueryService; - private final ApplicationEventPublisher applicationEventPublisher; public LineCommandService( final LineDao lineDao, final SectionCommandService sectionCommandService, - final LineQueryService lineQueryService, - final ApplicationEventPublisher applicationEventPublisher) { + final LineQueryService lineQueryService) { this.lineDao = lineDao; this.sectionCommandService = sectionCommandService; this.lineQueryService = lineQueryService; - this.applicationEventPublisher = applicationEventPublisher; } public void deleteLine(final Long lineId) { @@ -49,7 +44,5 @@ public void registerLine(final RegisterLineRequest registerLineRequest) { registerLineRequest.getDistance(), savedId ); - - applicationEventPublisher.publishEvent(new StationChange()); } } diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/service/StationService.java index fed84613b..23daad8ca 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/service/StationService.java @@ -3,14 +3,12 @@ import java.util.List; import java.util.Objects; import java.util.function.Consumer; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.line.Line; import subway.domain.section.Section; import subway.domain.station.Station; import subway.domain.station.Stations; -import subway.event.StationChange; import subway.service.dto.StationDeleteRequest; import subway.service.dto.StationRegisterRequest; @@ -21,17 +19,14 @@ public class StationService { private final SectionCommandService sectionCommandService; private final LineCommandService lineCommandService; private final LineQueryService lineQueryService; - private final ApplicationEventPublisher applicationEventPublisher; public StationService( final SectionCommandService sectionCommandService, final LineCommandService lineCommandService, - final LineQueryService lineQueryService, - final ApplicationEventPublisher applicationEventPublisher) { + final LineQueryService lineQueryService) { this.sectionCommandService = sectionCommandService; this.lineCommandService = lineCommandService; this.lineQueryService = lineQueryService; - this.applicationEventPublisher = applicationEventPublisher; } public void registerStation(final StationRegisterRequest stationRegisterRequest) { @@ -57,8 +52,6 @@ public void registerStation(final StationRegisterRequest stationRegisterRequest) .filter(section -> Objects.nonNull(section.getId())) .findFirst() .ifPresent(sectionCommandService::updateSection); - - applicationEventPublisher.publishEvent(new StationChange()); } private Section mapToSectionFrom(final StationRegisterRequest stationRegisterRequest) { @@ -94,8 +87,6 @@ public void deleteStation(final StationDeleteRequest stationDeleteRequest) { sectionCommandService.deleteAll(line.getId()); lineCommandService.deleteLine(line.getId()); } - - applicationEventPublisher.publishEvent(new StationChange()); } private Consumer
updateAndDeleteSection( From 1390aaffe1c0a14cc60fea219a9e3bb1f8d3a665 Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 18:17:33 +0900 Subject: [PATCH 40/41] =?UTF-8?q?refactor=20:=20=EA=B7=B8=EB=9E=98?= =?UTF-8?q?=ED=94=84=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20Factory=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 경로, 거리, 가격을 계산하는 유틸리티 클래스 생성 - RouteFinder 인터페이스 삭제 - 요금 관련 정책 파라미터 변경 --- build.gradle | 2 + .../subway/controller/LineController.java | 6 +- .../subway/controller/StationController.java | 3 +- .../domain/policy/ChargePolicyComposite.java | 13 +-- .../policy/fare/DistanceFarePolicy.java | 9 +- .../domain/policy/fare/LineFarePolicy.java | 13 +-- .../domain/policy/fare/SubwayFarePolicy.java | 5 +- .../domain/route/DijkstraGraphFactory.java | 70 ++++++++++++++ .../domain/route/JgraphtRouteFinder.java | 96 ++++--------------- .../java/subway/domain/route/RouteFinder.java | 14 --- .../subway/service/RouteQueryService.java | 31 +++--- .../policy/ChargePolicyCompositeTest.java | 9 +- .../policy/fare/DistanceFarePolicyTest.java | 53 ++++++++-- .../domain/route/JgraphtRouteFinderTest.java | 32 ------- 14 files changed, 184 insertions(+), 172 deletions(-) create mode 100644 src/main/java/subway/domain/route/DijkstraGraphFactory.java delete mode 100644 src/main/java/subway/domain/route/RouteFinder.java delete mode 100644 src/test/java/subway/domain/route/JgraphtRouteFinderTest.java diff --git a/build.gradle b/build.gradle index 1adbb34a8..f4ce241eb 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,8 @@ dependencies { implementation 'mysql:mysql-connector-java:8.0.33' implementation 'org.jgrapht:jgrapht-core:1.5.2' + + implementation 'org.mockito:mockito-inline:3.4.6' } test { diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/controller/LineController.java index c100d692b..9f44f0106 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/controller/LineController.java @@ -23,8 +23,10 @@ public class LineController { private final LineCommandService lineCommandService; private final LineQueryService lineQueryService; - public LineController(final LineCommandService lineCommandService, - final LineQueryService lineQueryService) { + public LineController( + final LineCommandService lineCommandService, + final LineQueryService lineQueryService + ) { this.lineCommandService = lineCommandService; this.lineQueryService = lineQueryService; } diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/controller/StationController.java index 94e6a4f82..431336f5a 100644 --- a/src/main/java/subway/controller/StationController.java +++ b/src/main/java/subway/controller/StationController.java @@ -23,7 +23,8 @@ public StationController(final StationService stationService) { @PostMapping("/stations") @ResponseStatus(HttpStatus.CREATED) public StationRegisterResponse registerStation( - @RequestBody StationRegisterRequest stationRegisterRequest) { + @RequestBody StationRegisterRequest stationRegisterRequest + ) { stationService.registerStation(stationRegisterRequest); return new StationRegisterResponse( diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/domain/policy/ChargePolicyComposite.java index 26c48b4bf..7365558e6 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/domain/policy/ChargePolicyComposite.java @@ -2,10 +2,10 @@ import java.util.List; import subway.domain.Money; +import subway.domain.line.Line; import subway.domain.policy.discount.DiscountCondition; import subway.domain.policy.discount.SubwayDiscountPolicy; import subway.domain.policy.fare.SubwayFarePolicy; -import subway.domain.route.RouteFinder; import subway.domain.station.Station; public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { @@ -25,18 +25,13 @@ public ChargePolicyComposite( public Money discount(final DiscountCondition discountCondition, final Money price) { return discountPolicies.stream() .reduce(price, (money, subwayDiscountPolicy) -> - subwayDiscountPolicy.discount(discountCondition, money), - (money1, money2) -> money2); + subwayDiscountPolicy.discount(discountCondition, money), (money1, money2) -> money2); } @Override - public Money calculate( - final RouteFinder routeFinder, - final Station departure, - final Station arrival - ) { + public Money calculate(final List lines, final Station departure, final Station arrival) { return farePolicies.stream() - .map(it -> it.calculate(routeFinder, departure, arrival)) + .map(it -> it.calculate(lines, departure, arrival)) .reduce(Money.ZERO, Money::add); } } diff --git a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java index 1c341442b..1c2a57d87 100644 --- a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java @@ -4,9 +4,11 @@ import static subway.domain.Distance.MID_DISTANCE; import java.math.BigDecimal; +import java.util.List; import subway.domain.Distance; import subway.domain.Money; -import subway.domain.route.RouteFinder; +import subway.domain.line.Line; +import subway.domain.route.JgraphtRouteFinder; import subway.domain.station.Station; public class DistanceFarePolicy implements SubwayFarePolicy { @@ -17,9 +19,10 @@ public class DistanceFarePolicy implements SubwayFarePolicy { private static final int LONG_DISTANCE_RATE = 8; @Override - public Money calculate(final RouteFinder routeFinder, final Station departure, + public Money calculate(final List lines, final Station departure, final Station arrival) { - final Distance distance = routeFinder.findShortestRouteDistance(departure, arrival); + final Distance distance = + JgraphtRouteFinder.findShortestRouteDistance(lines, departure, arrival); if (distance.isDefaultDistance()) { return DEFAULT_PRICE; diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java index c5605ef66..0ae47315a 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/LineFarePolicy.java @@ -3,8 +3,9 @@ import java.util.List; import java.util.Map; import subway.domain.Money; +import subway.domain.line.Line; import subway.domain.route.EdgeSection; -import subway.domain.route.RouteFinder; +import subway.domain.route.JgraphtRouteFinder; import subway.domain.station.Station; public class LineFarePolicy implements SubwayFarePolicy { @@ -14,13 +15,9 @@ public class LineFarePolicy implements SubwayFarePolicy { "2호선", 1000); @Override - public Money calculate( - final RouteFinder routeFinder, - final Station departure, - final Station arrival - ) { - final List shortestRouteSections = routeFinder.findShortestRouteSections(departure, - arrival); + public Money calculate(final List lines, final Station departure, final Station arrival) { + final List shortestRouteSections = + JgraphtRouteFinder.findShortestRouteSections(lines, departure, arrival); return shortestRouteSections.stream() .reduce(Money.ZERO, (money, edgeSection) -> diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java index bfd348556..cae162cce 100644 --- a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java +++ b/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java @@ -1,10 +1,11 @@ package subway.domain.policy.fare; +import java.util.List; import subway.domain.Money; -import subway.domain.route.RouteFinder; +import subway.domain.line.Line; import subway.domain.station.Station; public interface SubwayFarePolicy { - Money calculate(final RouteFinder routeFinder, final Station departure, final Station arrival); + Money calculate(final List lines, final Station departure, final Station arrival); } diff --git a/src/main/java/subway/domain/route/DijkstraGraphFactory.java b/src/main/java/subway/domain/route/DijkstraGraphFactory.java new file mode 100644 index 000000000..69c216e51 --- /dev/null +++ b/src/main/java/subway/domain/route/DijkstraGraphFactory.java @@ -0,0 +1,70 @@ +package subway.domain.route; + +import java.util.List; +import org.jgrapht.Graph; +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.WeightedMultigraph; +import subway.domain.line.Line; +import subway.domain.section.Section; +import subway.domain.station.Station; +import subway.domain.station.Stations; + +public class DijkstraGraphFactory { + + private DijkstraGraphFactory() { + } + + public static DijkstraShortestPath makeDijkstraGraph( + final List lines) { + Graph graph + = new WeightedMultigraph<>(EdgeSection.class); + + for (final Line line : lines) { + makeGraphFromSections(graph, line); + } + + return new DijkstraShortestPath<>(graph); + } + + private static void makeGraphFromSections( + final Graph graph, + final Line line + ) { + + final List
sections = line.getSections(); + + for (final Section section : sections) { + final Stations stations = section.getStations(); + + final String startStation = stations.getCurrent().getName(); + final String endStation = stations.getNext().getName(); + final int distance = stations.getDistance(); + + addVertex(graph, startStation, endStation); + addEdge(graph, startStation, endStation, distance, line.getName()); + } + } + + private static void addVertex( + final Graph graph, + final String startStation, + final String endStation + ) { + graph.addVertex(new Station(startStation)); + graph.addVertex(new Station(endStation)); + } + + private static void addEdge( + final Graph graph, final String startStation, + final String endStation, final int distance, final String lineName + ) { + final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); + final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); + + graph.addEdge(new Station(startStation), new Station(endStation), start); + graph.addEdge(new Station(endStation), new Station(startStation), end); + + graph.setEdgeWeight(start, distance); + graph.setEdgeWeight(end, distance); + } +} diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/domain/route/JgraphtRouteFinder.java index ee3064c39..825bb210a 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/domain/route/JgraphtRouteFinder.java @@ -1,96 +1,38 @@ package subway.domain.route; import java.util.List; -import org.jgrapht.Graph; -import org.jgrapht.alg.shortestpath.DijkstraShortestPath; -import org.jgrapht.graph.WeightedMultigraph; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; import subway.domain.Distance; import subway.domain.line.Line; -import subway.domain.section.Section; import subway.domain.station.Station; -import subway.domain.station.Stations; -import subway.event.StationChange; -import subway.service.LineQueryService; -@Component -public class JgraphtRouteFinder implements RouteFinder { +public class JgraphtRouteFinder { - private DijkstraShortestPath dijkstraGraph; - private final LineQueryService lineQueryService; - - public JgraphtRouteFinder(final LineQueryService lineQueryService) { - this.lineQueryService = lineQueryService; + private JgraphtRouteFinder() { } - @EventListener({ContextRefreshedEvent.class, StationChange.class}) - public void updateDijkstraGraph() { - final List lines = lineQueryService.searchAllLine(); - - Graph graph - = new WeightedMultigraph<>(EdgeSection.class); - - for (final Line line : lines) { - makeGraphFromSections(graph, line); - } - - dijkstraGraph = new DijkstraShortestPath<>(graph); - } - - private void makeGraphFromSections( - final Graph graph, - final Line line + public static List findShortestRoute( + final List lines, + final Station departure, + final Station arrival ) { - - final List
sections = line.getSections(); - - for (final Section section : sections) { - final Stations stations = section.getStations(); - - final String startStation = stations.getCurrent().getName(); - final String endStation = stations.getNext().getName(); - final int distance = stations.getDistance(); - - addVertex(graph, startStation, endStation); - addEdge(graph, startStation, endStation, distance, line.getName()); - } + return DijkstraGraphFactory.makeDijkstraGraph(lines).getPath(departure, arrival) + .getVertexList(); } - private void addVertex( - final Graph graph, - final String startStation, - final String endStation + public static Distance findShortestRouteDistance( + final List lines, + final Station departure, + final Station arrival ) { - graph.addVertex(new Station(startStation)); - graph.addVertex(new Station(endStation)); + return new Distance( + (int) DijkstraGraphFactory.makeDijkstraGraph(lines).getPathWeight(departure, arrival)); } - private void addEdge( - final Graph graph, final String startStation, - final String endStation, final int distance, final String lineName + public static List findShortestRouteSections( + final List lines, + final Station departure, + final Station arrival ) { - final EdgeSection start = new EdgeSection(startStation, endStation, distance, lineName); - final EdgeSection end = new EdgeSection(endStation, startStation, distance, lineName); - - graph.addEdge(new Station(startStation), new Station(endStation), start); - graph.addEdge(new Station(endStation), new Station(startStation), end); - - graph.setEdgeWeight(start, distance); - graph.setEdgeWeight(end, distance); - } - - public List findShortestRoute(final Station departure, final Station arrival) { - return dijkstraGraph.getPath(departure, arrival).getVertexList(); - } - - public Distance findShortestRouteDistance(final Station departure, final Station arrival) { - return new Distance((int) dijkstraGraph.getPathWeight(departure, arrival)); - } - - public List findShortestRouteSections(final Station departure, - final Station arrival) { - return dijkstraGraph.getPath(departure, arrival).getEdgeList(); + return DijkstraGraphFactory.makeDijkstraGraph(lines).getPath(departure, arrival).getEdgeList(); } } diff --git a/src/main/java/subway/domain/route/RouteFinder.java b/src/main/java/subway/domain/route/RouteFinder.java deleted file mode 100644 index 3bbfca55c..000000000 --- a/src/main/java/subway/domain/route/RouteFinder.java +++ /dev/null @@ -1,14 +0,0 @@ -package subway.domain.route; - -import java.util.List; -import subway.domain.Distance; -import subway.domain.station.Station; - -public interface RouteFinder { - - List findShortestRoute(final Station departure, final Station arrival); - - Distance findShortestRouteDistance(final Station departure, final Station arrival); - - List findShortestRouteSections(final Station departure, final Station arrival); -} diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/service/RouteQueryService.java index 10ef50a8b..4dd1af64d 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/service/RouteQueryService.java @@ -5,6 +5,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import subway.domain.Money; +import subway.domain.line.Line; import subway.domain.policy.ChargePolicyComposite; import subway.domain.policy.discount.DiscountCondition; import subway.domain.route.JgraphtRouteFinder; @@ -16,28 +17,30 @@ @Transactional(readOnly = true) public class RouteQueryService { - private final ChargePolicyComposite chargePolicyComposite2; - private final JgraphtRouteFinder jgraphtRouteFinder; + private final ChargePolicyComposite chargePolicyComposite; + private final LineQueryService lineQueryService; public RouteQueryService( - final ChargePolicyComposite chargePolicyComposite2, - final JgraphtRouteFinder jgraphtRouteFinder + final ChargePolicyComposite chargePolicyComposite, + final LineQueryService lineQueryService ) { - this.chargePolicyComposite2 = chargePolicyComposite2; - this.jgraphtRouteFinder = jgraphtRouteFinder; + this.chargePolicyComposite = chargePolicyComposite; + this.lineQueryService = lineQueryService; } public ShortestRouteResponse searchShortestRoute( final ShortestRouteRequest shortestRouteRequest ) { + final List lines = lineQueryService.searchAllLine(); + final Station departure = new Station(shortestRouteRequest.getStartStation()); final Station arrival = new Station(shortestRouteRequest.getEndStation()); return new ShortestRouteResponse( - mapToStationNameFrom(jgraphtRouteFinder.findShortestRoute(departure, arrival)), - searchCost(departure, arrival, shortestRouteRequest.getAge()).getValue(), - jgraphtRouteFinder.findShortestRouteDistance(departure, arrival).getValue() + mapToStationNameFrom(JgraphtRouteFinder.findShortestRoute(lines, departure, arrival)), + searchCost(lines, departure, arrival, shortestRouteRequest.getAge()).getValue(), + JgraphtRouteFinder.findShortestRouteDistance(lines, departure, arrival).getValue() ); } @@ -47,10 +50,12 @@ private List mapToStationNameFrom(final List stations) { .collect(Collectors.toList()); } - private Money searchCost(final Station departure, final Station arrival, final Integer age) { - final Money totalPrice = chargePolicyComposite2.calculate(jgraphtRouteFinder, departure, - arrival); + private Money searchCost( + final List lines, final Station departure, + final Station arrival, final Integer age + ) { + final Money totalPrice = chargePolicyComposite.calculate(lines, departure, arrival); - return chargePolicyComposite2.discount(new DiscountCondition(age), totalPrice); + return chargePolicyComposite.discount(new DiscountCondition(age), totalPrice); } } diff --git a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java index ef1a7ba69..99fb1c00e 100644 --- a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java @@ -9,12 +9,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import subway.domain.Money; +import subway.domain.line.Line; import subway.domain.policy.discount.AgeDiscountPolicy; import subway.domain.policy.discount.DiscountCondition; import subway.domain.policy.fare.DistanceFarePolicy; import subway.domain.policy.fare.LineFarePolicy; -import subway.domain.route.RouteFinder; import subway.domain.station.Station; +import subway.service.LineQueryService; @SpringBootTest class ChargePolicyCompositeTest { @@ -23,7 +24,7 @@ class ChargePolicyCompositeTest { private ChargePolicyComposite pricePolicyComposite; @Autowired - private RouteFinder routeFinder; + private LineQueryService lineQueryService; @BeforeEach void setUp() { @@ -43,16 +44,16 @@ void setUp() { * A - B - C - D * 1 2 3 */ - @Test @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") void test_calculate() throws Exception { //given final Station departure = new Station("A"); final Station arrival = new Station("G"); + final List lines = lineQueryService.searchAllLine(); //when - final Money totalMoney = pricePolicyComposite.calculate(routeFinder, departure, arrival); + final Money totalMoney = pricePolicyComposite.calculate(lines, departure, arrival); //then assertEquals(new Money(2350), totalMoney); diff --git a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java index 42c7e9c63..38ee6a502 100644 --- a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java +++ b/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java @@ -2,44 +2,56 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mockStatic; +import java.util.List; import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.MockedStatic; import subway.domain.Distance; import subway.domain.Money; -import subway.domain.route.RouteFinder; +import subway.domain.line.Line; +import subway.domain.route.JgraphtRouteFinder; +import subway.domain.section.Section; import subway.domain.station.Station; +import subway.domain.station.Stations; class DistanceFarePolicyTest { private SubwayFarePolicy subwayFarePolicy; - private RouteFinder routeFinder; + MockedStatic jgraphtRouteFinder; @BeforeEach void setUp() { - routeFinder = mock(RouteFinder.class); + jgraphtRouteFinder = mockStatic(JgraphtRouteFinder.class); subwayFarePolicy = new DistanceFarePolicy(); } + @AfterEach + void tearDown() { + jgraphtRouteFinder.close(); + } + @ParameterizedTest @MethodSource("calculatePriceFromDistance") @DisplayName("calculate() : 거리에 따라 요금을 계산할 수 있다.") void test_calculate(final Station departure, final Station arrival, final Money price, final Distance distance) throws Exception { //given - when(routeFinder.findShortestRouteDistance(any(), any())) + final List lines = createDefaultLines(); + + jgraphtRouteFinder.when(() -> JgraphtRouteFinder.findShortestRouteDistance(any(), any(), any())) .thenReturn(distance); //when - final Money result = subwayFarePolicy.calculate(routeFinder, departure, arrival); + final Money result = subwayFarePolicy.calculate(lines, departure, arrival); //then assertEquals(result, price); @@ -74,4 +86,31 @@ static Stream calculatePriceFromDistance() { Arguments.of(start4, end4, money4, distance4) ); } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } } diff --git a/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java b/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java deleted file mode 100644 index ba4469f19..000000000 --- a/src/test/java/subway/domain/route/JgraphtRouteFinderTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package subway.domain.route; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.ApplicationEventPublisher; -import subway.event.StationChange; - -@SpringBootTest -class JgraphtRouteFinderTest { - - @Autowired - private ApplicationEventPublisher applicationEventPublisher; - - @MockBean - private JgraphtRouteFinder jgraphtRouteFinder; - - @Test - @DisplayName("init() : 애플리케이션 컨테이너가 뜰 때와 역이 변경될 경우 이벤트가 실행될 수 있다.") - void test_init_eventListener() throws Exception { - //given - applicationEventPublisher.publishEvent(new StationChange()); - - //when & then - verify(jgraphtRouteFinder, times(2)).updateDijkstraGraph(); - } -} From 727c10b626b0cae78cb0be6f203beb6f4bd21e7b Mon Sep 17 00:00:00 2001 From: java-saeng Date: Thu, 25 May 2023 20:00:28 +0900 Subject: [PATCH 41/41] =?UTF-8?q?refactor=20:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subway/config/ChargePolicyConfig.java | 8 +- .../{common => }/BusinessException.java | 2 +- .../ExceptionHandlerController.java | 2 +- .../{common => }/ExceptionResponse.java | 2 +- .../CanNotDistanceEqualZeroException.java | 11 - .../application}/LineCommandService.java | 10 +- .../application}/LineQueryService.java | 10 +- .../application}/SectionCommandService.java | 14 +- .../application}/SectionQueryService.java | 12 +- .../application}/StationService.java | 14 +- .../application}/dto/LineResponse.java | 2 +- .../application}/dto/RegisterLineRequest.java | 2 +- .../application}/dto/SectionResponse.java | 2 +- .../dto/StationDeleteRequest.java | 2 +- .../dto/StationRegisterRequest.java | 2 +- .../dto/StationRegisterResponse.java | 6 +- .../java/subway/{ => line}/dao/LineDao.java | 2 +- .../subway/{ => line}/dao/LineEntity.java | 4 +- .../subway/{ => line}/dao/SectionDao.java | 2 +- .../subway/{ => line}/dao/SectionEntity.java | 12 +- .../{domain/line => line/domain}/Line.java | 4 +- .../section => line/domain}/Section.java | 4 +- .../station => line/domain}/Station.java | 2 +- .../station => line/domain}/Stations.java | 4 +- .../CanNotDuplicatedLineNameException.java | 4 +- .../CanNotDuplicatedSectionException.java | 4 +- .../exception}/CanNotFoundLineException.java | 4 +- .../presentation}/LineController.java | 14 +- .../presentation}/StationController.java | 10 +- .../application}/ChargePolicyComposite.java | 14 +- .../discount => policy/domain}/AgeGroup.java | 2 +- .../domain}/SubwayDiscountPolicy.java | 5 +- .../domain}/SubwayFarePolicy.java | 8 +- .../infrastructure}/AgeDiscountPolicy.java | 6 +- .../infrastructure}/DiscountCondition.java | 2 +- .../infrastructure}/DistanceFarePolicy.java | 17 +- .../infrastructure}/LineFarePolicy.java | 13 +- .../application}/JgraphtRouteFinder.java | 10 +- .../application}/RouteQueryService.java | 18 +- .../dto/ShortestRouteRequest.java | 2 +- .../dto/ShortestRouteResponse.java | 2 +- .../infrastructure}/DijkstraGraphFactory.java | 13 +- .../infrastructure}/EdgeSection.java | 2 +- .../presentation}/RouteController.java | 8 +- .../service/dto/LeastCostRouteResponse.java | 37 --- .../{domain => value_object}/Distance.java | 2 +- .../{domain => value_object}/Money.java | 2 +- .../java/helper/IntegrationTestHelper.java | 1 + .../subway/controller/LineControllerTest.java | 142 --------- .../controller/StationControllerTest.java | 77 ----- src/test/java/subway/dao/LineDaoTest.java | 109 ------- src/test/java/subway/dao/SectionDaoTest.java | 136 --------- src/test/java/subway/domain/MoneyTest.java | 47 --- .../java/subway/domain/line/LineTest.java | 279 ------------------ .../subway/domain/section/SectionTest.java | 191 ------------ .../subway/domain/station/StationTest.java | 20 -- .../subway/domain/station/StationsTest.java | 29 -- .../application/LineCommandServiceTest.java | 78 +++++ .../application/LineQueryServiceTest.java | 96 ++++++ .../SectionCommandServiceTest.java | 121 ++++++++ .../application/SectionQueryServiceTest.java | 29 ++ .../line/application/StationServiceTest.java | 102 +++++++ .../java/subway/line/dao/LineDaoTest.java | 108 +++++++ .../java/subway/line/dao/SectionDaoTest.java | 136 +++++++++ .../java/subway/line/domain/LineTest.java | 259 ++++++++++++++++ .../java/subway/line/domain/SectionTest.java | 179 +++++++++++ .../java/subway/line/domain/StationTest.java | 20 ++ .../java/subway/line/domain/StationsTest.java | 29 ++ .../line/presentation/LineControllerTest.java | 141 +++++++++ .../presentation/StationControllerTest.java | 78 +++++ .../ChargePolicyCompositeTest.java | 26 +- .../DistanceFarePolicyTest.java | 17 +- .../application}/RouteQueryServiceTest.java | 6 +- .../presentation}/RouteControllerTest.java | 6 +- .../service/LineCommandServiceTest.java | 79 ----- .../subway/service/LineQueryServiceTest.java | 97 ------ .../service/SectionCommandServiceTest.java | 119 -------- .../service/SectionQueryServiceTest.java | 30 -- .../subway/service/StationServiceTest.java | 102 ------- .../java/subway/value_object/MoneyTest.java | 48 +++ .../subway/yml/ProfileActiveFirstTest.java | 31 +- .../subway/yml/ProfileActiveSecondTest.java | 31 +- .../subway/yml/ProfileActiveThirdTest.java | 31 +- 83 files changed, 1640 insertions(+), 1724 deletions(-) rename src/main/java/subway/exception/{common => }/BusinessException.java (91%) rename src/main/java/subway/exception/{common => }/ExceptionHandlerController.java (98%) rename src/main/java/subway/exception/{common => }/ExceptionResponse.java (86%) delete mode 100644 src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java rename src/main/java/subway/{service => line/application}/LineCommandService.java (85%) rename src/main/java/subway/{service => line/application}/LineQueryService.java (91%) rename src/main/java/subway/{service => line/application}/SectionCommandService.java (88%) rename src/main/java/subway/{service => line/application}/SectionQueryService.java (81%) rename src/main/java/subway/{service => line/application}/StationService.java (92%) rename src/main/java/subway/{service => line/application}/dto/LineResponse.java (93%) rename src/main/java/subway/{service => line/application}/dto/RegisterLineRequest.java (95%) rename src/main/java/subway/{service => line/application}/dto/SectionResponse.java (94%) rename src/main/java/subway/{service => line/application}/dto/StationDeleteRequest.java (91%) rename src/main/java/subway/{service => line/application}/dto/StationRegisterRequest.java (95%) rename src/main/java/subway/{service => line/application}/dto/StationRegisterResponse.java (75%) rename src/main/java/subway/{ => line}/dao/LineDao.java (98%) rename src/main/java/subway/{ => line}/dao/LineEntity.java (85%) rename src/main/java/subway/{ => line}/dao/SectionDao.java (98%) rename src/main/java/subway/{ => line}/dao/SectionEntity.java (85%) rename src/main/java/subway/{domain/line => line/domain}/Line.java (97%) rename src/main/java/subway/{domain/section => line/domain}/Section.java (97%) rename src/main/java/subway/{domain/station => line/domain}/Station.java (96%) rename src/main/java/subway/{domain/station => line/domain}/Stations.java (95%) rename src/main/java/subway/{exception/line => line/exception}/CanNotDuplicatedLineNameException.java (74%) rename src/main/java/subway/{exception/section => line/exception}/CanNotDuplicatedSectionException.java (73%) rename src/main/java/subway/{exception/line => line/exception}/CanNotFoundLineException.java (73%) rename src/main/java/subway/{controller => line/presentation}/LineController.java (88%) rename src/main/java/subway/{controller => line/presentation}/StationController.java (82%) rename src/main/java/subway/{domain/policy => policy/application}/ChargePolicyComposite.java (77%) rename src/main/java/subway/{domain/policy/discount => policy/domain}/AgeGroup.java (93%) rename src/main/java/subway/{domain/policy/discount => policy/domain}/SubwayDiscountPolicy.java (51%) rename src/main/java/subway/{domain/policy/fare => policy/domain}/SubwayFarePolicy.java (53%) rename src/main/java/subway/{domain/policy/discount => policy/infrastructure}/AgeDiscountPolicy.java (88%) rename src/main/java/subway/{domain/policy/discount => policy/infrastructure}/DiscountCondition.java (82%) rename src/main/java/subway/{domain/policy/fare => policy/infrastructure}/DistanceFarePolicy.java (78%) rename src/main/java/subway/{domain/policy/fare => policy/infrastructure}/LineFarePolicy.java (70%) rename src/main/java/subway/{domain/route => route/application}/JgraphtRouteFinder.java (78%) rename src/main/java/subway/{service => route/application}/RouteQueryService.java (81%) rename src/main/java/subway/{service => route/application}/dto/ShortestRouteRequest.java (93%) rename src/main/java/subway/{service => route/application}/dto/ShortestRouteResponse.java (93%) rename src/main/java/subway/{domain/route => route/infrastructure}/DijkstraGraphFactory.java (90%) rename src/main/java/subway/{domain/route => route/infrastructure}/EdgeSection.java (95%) rename src/main/java/subway/{controller => route/presentation}/RouteController.java (75%) delete mode 100644 src/main/java/subway/service/dto/LeastCostRouteResponse.java rename src/main/java/subway/{domain => value_object}/Distance.java (98%) rename src/main/java/subway/{domain => value_object}/Money.java (98%) delete mode 100644 src/test/java/subway/controller/LineControllerTest.java delete mode 100644 src/test/java/subway/controller/StationControllerTest.java delete mode 100644 src/test/java/subway/dao/LineDaoTest.java delete mode 100644 src/test/java/subway/dao/SectionDaoTest.java delete mode 100644 src/test/java/subway/domain/MoneyTest.java delete mode 100644 src/test/java/subway/domain/line/LineTest.java delete mode 100644 src/test/java/subway/domain/section/SectionTest.java delete mode 100644 src/test/java/subway/domain/station/StationTest.java delete mode 100644 src/test/java/subway/domain/station/StationsTest.java create mode 100644 src/test/java/subway/line/application/LineCommandServiceTest.java create mode 100644 src/test/java/subway/line/application/LineQueryServiceTest.java create mode 100644 src/test/java/subway/line/application/SectionCommandServiceTest.java create mode 100644 src/test/java/subway/line/application/SectionQueryServiceTest.java create mode 100644 src/test/java/subway/line/application/StationServiceTest.java create mode 100644 src/test/java/subway/line/dao/LineDaoTest.java create mode 100644 src/test/java/subway/line/dao/SectionDaoTest.java create mode 100644 src/test/java/subway/line/domain/LineTest.java create mode 100644 src/test/java/subway/line/domain/SectionTest.java create mode 100644 src/test/java/subway/line/domain/StationTest.java create mode 100644 src/test/java/subway/line/domain/StationsTest.java create mode 100644 src/test/java/subway/line/presentation/LineControllerTest.java create mode 100644 src/test/java/subway/line/presentation/StationControllerTest.java rename src/test/java/subway/{domain/policy => policy/application}/ChargePolicyCompositeTest.java (75%) rename src/test/java/subway/{domain/policy/fare => policy/infrastructure}/DistanceFarePolicyTest.java (91%) rename src/test/java/subway/{service => route/application}/RouteQueryServiceTest.java (89%) rename src/test/java/subway/{controller => route/presentation}/RouteControllerTest.java (94%) delete mode 100644 src/test/java/subway/service/LineCommandServiceTest.java delete mode 100644 src/test/java/subway/service/LineQueryServiceTest.java delete mode 100644 src/test/java/subway/service/SectionCommandServiceTest.java delete mode 100644 src/test/java/subway/service/SectionQueryServiceTest.java delete mode 100644 src/test/java/subway/service/StationServiceTest.java create mode 100644 src/test/java/subway/value_object/MoneyTest.java diff --git a/src/main/java/subway/config/ChargePolicyConfig.java b/src/main/java/subway/config/ChargePolicyConfig.java index 045825e60..621c834ca 100644 --- a/src/main/java/subway/config/ChargePolicyConfig.java +++ b/src/main/java/subway/config/ChargePolicyConfig.java @@ -3,10 +3,10 @@ import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import subway.domain.policy.ChargePolicyComposite; -import subway.domain.policy.discount.AgeDiscountPolicy; -import subway.domain.policy.fare.DistanceFarePolicy; -import subway.domain.policy.fare.LineFarePolicy; +import subway.policy.application.ChargePolicyComposite; +import subway.policy.infrastructure.AgeDiscountPolicy; +import subway.policy.infrastructure.DistanceFarePolicy; +import subway.policy.infrastructure.LineFarePolicy; @Configuration public class ChargePolicyConfig { diff --git a/src/main/java/subway/exception/common/BusinessException.java b/src/main/java/subway/exception/BusinessException.java similarity index 91% rename from src/main/java/subway/exception/common/BusinessException.java rename to src/main/java/subway/exception/BusinessException.java index f3caa228f..0f664887e 100644 --- a/src/main/java/subway/exception/common/BusinessException.java +++ b/src/main/java/subway/exception/BusinessException.java @@ -1,4 +1,4 @@ -package subway.exception.common; +package subway.exception; import org.springframework.http.HttpStatus; diff --git a/src/main/java/subway/exception/common/ExceptionHandlerController.java b/src/main/java/subway/exception/ExceptionHandlerController.java similarity index 98% rename from src/main/java/subway/exception/common/ExceptionHandlerController.java rename to src/main/java/subway/exception/ExceptionHandlerController.java index a2f9a8446..c4c919539 100644 --- a/src/main/java/subway/exception/common/ExceptionHandlerController.java +++ b/src/main/java/subway/exception/ExceptionHandlerController.java @@ -1,4 +1,4 @@ -package subway.exception.common; +package subway.exception; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/subway/exception/common/ExceptionResponse.java b/src/main/java/subway/exception/ExceptionResponse.java similarity index 86% rename from src/main/java/subway/exception/common/ExceptionResponse.java rename to src/main/java/subway/exception/ExceptionResponse.java index f42af0baa..52a5348ec 100644 --- a/src/main/java/subway/exception/common/ExceptionResponse.java +++ b/src/main/java/subway/exception/ExceptionResponse.java @@ -1,4 +1,4 @@ -package subway.exception.common; +package subway.exception; public class ExceptionResponse { diff --git a/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java b/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java deleted file mode 100644 index b4b76dc88..000000000 --- a/src/main/java/subway/exception/pricepolicy/CanNotDistanceEqualZeroException.java +++ /dev/null @@ -1,11 +0,0 @@ -package subway.exception.pricepolicy; - -import org.springframework.http.HttpStatus; -import subway.exception.common.BusinessException; - -public class CanNotDistanceEqualZeroException extends BusinessException { - - public CanNotDistanceEqualZeroException(final String message) { - super(message, HttpStatus.BAD_REQUEST); - } -} diff --git a/src/main/java/subway/service/LineCommandService.java b/src/main/java/subway/line/application/LineCommandService.java similarity index 85% rename from src/main/java/subway/service/LineCommandService.java rename to src/main/java/subway/line/application/LineCommandService.java index d2abd8afe..a8dab45a4 100644 --- a/src/main/java/subway/service/LineCommandService.java +++ b/src/main/java/subway/line/application/LineCommandService.java @@ -1,11 +1,11 @@ -package subway.service; +package subway.line.application; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.dao.LineDao; -import subway.dao.LineEntity; -import subway.exception.line.CanNotDuplicatedLineNameException; -import subway.service.dto.RegisterLineRequest; +import subway.line.dao.LineDao; +import subway.line.dao.LineEntity; +import subway.line.exception.CanNotDuplicatedLineNameException; +import subway.line.application.dto.RegisterLineRequest; @Service @Transactional diff --git a/src/main/java/subway/service/LineQueryService.java b/src/main/java/subway/line/application/LineQueryService.java similarity index 91% rename from src/main/java/subway/service/LineQueryService.java rename to src/main/java/subway/line/application/LineQueryService.java index e4672887e..44ffdef70 100644 --- a/src/main/java/subway/service/LineQueryService.java +++ b/src/main/java/subway/line/application/LineQueryService.java @@ -1,13 +1,13 @@ -package subway.service; +package subway.line.application; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.dao.LineDao; -import subway.dao.LineEntity; -import subway.domain.line.Line; -import subway.exception.line.CanNotFoundLineException; +import subway.line.dao.LineDao; +import subway.line.dao.LineEntity; +import subway.line.domain.Line; +import subway.line.exception.CanNotFoundLineException; @Service @Transactional(readOnly = true) diff --git a/src/main/java/subway/service/SectionCommandService.java b/src/main/java/subway/line/application/SectionCommandService.java similarity index 88% rename from src/main/java/subway/service/SectionCommandService.java rename to src/main/java/subway/line/application/SectionCommandService.java index 12ae4a33d..16fb1f517 100644 --- a/src/main/java/subway/service/SectionCommandService.java +++ b/src/main/java/subway/line/application/SectionCommandService.java @@ -1,14 +1,14 @@ -package subway.service; +package subway.line.application; import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.dao.SectionDao; -import subway.dao.SectionEntity; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; -import subway.exception.section.CanNotDuplicatedSectionException; +import subway.line.dao.SectionDao; +import subway.line.dao.SectionEntity; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; +import subway.line.exception.CanNotDuplicatedSectionException; @Service @Transactional diff --git a/src/main/java/subway/service/SectionQueryService.java b/src/main/java/subway/line/application/SectionQueryService.java similarity index 81% rename from src/main/java/subway/service/SectionQueryService.java rename to src/main/java/subway/line/application/SectionQueryService.java index 47b3ad337..1a09e839c 100644 --- a/src/main/java/subway/service/SectionQueryService.java +++ b/src/main/java/subway/line/application/SectionQueryService.java @@ -1,14 +1,14 @@ -package subway.service; +package subway.line.application; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.dao.SectionDao; -import subway.dao.SectionEntity; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; +import subway.line.dao.SectionDao; +import subway.line.dao.SectionEntity; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; @Service @Transactional(readOnly = true) diff --git a/src/main/java/subway/service/StationService.java b/src/main/java/subway/line/application/StationService.java similarity index 92% rename from src/main/java/subway/service/StationService.java rename to src/main/java/subway/line/application/StationService.java index 23daad8ca..e2ce5b6ec 100644 --- a/src/main/java/subway/service/StationService.java +++ b/src/main/java/subway/line/application/StationService.java @@ -1,16 +1,16 @@ -package subway.service; +package subway.line.application; import java.util.List; import java.util.Objects; import java.util.function.Consumer; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.domain.line.Line; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; -import subway.service.dto.StationDeleteRequest; -import subway.service.dto.StationRegisterRequest; +import subway.line.domain.Line; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; +import subway.line.application.dto.StationDeleteRequest; +import subway.line.application.dto.StationRegisterRequest; @Service @Transactional diff --git a/src/main/java/subway/service/dto/LineResponse.java b/src/main/java/subway/line/application/dto/LineResponse.java similarity index 93% rename from src/main/java/subway/service/dto/LineResponse.java rename to src/main/java/subway/line/application/dto/LineResponse.java index 0bf844869..e0052a4da 100644 --- a/src/main/java/subway/service/dto/LineResponse.java +++ b/src/main/java/subway/line/application/dto/LineResponse.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.line.application.dto; import java.util.List; diff --git a/src/main/java/subway/service/dto/RegisterLineRequest.java b/src/main/java/subway/line/application/dto/RegisterLineRequest.java similarity index 95% rename from src/main/java/subway/service/dto/RegisterLineRequest.java rename to src/main/java/subway/line/application/dto/RegisterLineRequest.java index bdf7471a8..94ca56cad 100644 --- a/src/main/java/subway/service/dto/RegisterLineRequest.java +++ b/src/main/java/subway/line/application/dto/RegisterLineRequest.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.line.application.dto; public class RegisterLineRequest { diff --git a/src/main/java/subway/service/dto/SectionResponse.java b/src/main/java/subway/line/application/dto/SectionResponse.java similarity index 94% rename from src/main/java/subway/service/dto/SectionResponse.java rename to src/main/java/subway/line/application/dto/SectionResponse.java index 847386d09..8b315a96d 100644 --- a/src/main/java/subway/service/dto/SectionResponse.java +++ b/src/main/java/subway/line/application/dto/SectionResponse.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.line.application.dto; public class SectionResponse { diff --git a/src/main/java/subway/service/dto/StationDeleteRequest.java b/src/main/java/subway/line/application/dto/StationDeleteRequest.java similarity index 91% rename from src/main/java/subway/service/dto/StationDeleteRequest.java rename to src/main/java/subway/line/application/dto/StationDeleteRequest.java index 6201efe3a..2bcd0d16e 100644 --- a/src/main/java/subway/service/dto/StationDeleteRequest.java +++ b/src/main/java/subway/line/application/dto/StationDeleteRequest.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.line.application.dto; public class StationDeleteRequest { diff --git a/src/main/java/subway/service/dto/StationRegisterRequest.java b/src/main/java/subway/line/application/dto/StationRegisterRequest.java similarity index 95% rename from src/main/java/subway/service/dto/StationRegisterRequest.java rename to src/main/java/subway/line/application/dto/StationRegisterRequest.java index aba166957..385087ae2 100644 --- a/src/main/java/subway/service/dto/StationRegisterRequest.java +++ b/src/main/java/subway/line/application/dto/StationRegisterRequest.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.line.application.dto; public class StationRegisterRequest { diff --git a/src/main/java/subway/service/dto/StationRegisterResponse.java b/src/main/java/subway/line/application/dto/StationRegisterResponse.java similarity index 75% rename from src/main/java/subway/service/dto/StationRegisterResponse.java rename to src/main/java/subway/line/application/dto/StationRegisterResponse.java index 97ef9b2bf..cda0f6e56 100644 --- a/src/main/java/subway/service/dto/StationRegisterResponse.java +++ b/src/main/java/subway/line/application/dto/StationRegisterResponse.java @@ -1,9 +1,9 @@ -package subway.service.dto; +package subway.line.application.dto; public class StationRegisterResponse { - private String lineName; - private String stationName; + private final String lineName; + private final String stationName; public StationRegisterResponse(final String lineName, final String stationName) { this.lineName = lineName; diff --git a/src/main/java/subway/dao/LineDao.java b/src/main/java/subway/line/dao/LineDao.java similarity index 98% rename from src/main/java/subway/dao/LineDao.java rename to src/main/java/subway/line/dao/LineDao.java index 7df3c8565..12ab5e366 100644 --- a/src/main/java/subway/dao/LineDao.java +++ b/src/main/java/subway/line/dao/LineDao.java @@ -1,4 +1,4 @@ -package subway.dao; +package subway.line.dao; import java.util.List; import java.util.Optional; diff --git a/src/main/java/subway/dao/LineEntity.java b/src/main/java/subway/line/dao/LineEntity.java similarity index 85% rename from src/main/java/subway/dao/LineEntity.java rename to src/main/java/subway/line/dao/LineEntity.java index 43c3af7a1..787340ddd 100644 --- a/src/main/java/subway/dao/LineEntity.java +++ b/src/main/java/subway/line/dao/LineEntity.java @@ -1,9 +1,9 @@ -package subway.dao; +package subway.line.dao; public class LineEntity { private Long id; - private String name; + private final String name; public LineEntity(final Long id, final String name) { this.id = id; diff --git a/src/main/java/subway/dao/SectionDao.java b/src/main/java/subway/line/dao/SectionDao.java similarity index 98% rename from src/main/java/subway/dao/SectionDao.java rename to src/main/java/subway/line/dao/SectionDao.java index 7e70efabd..6f754dca4 100644 --- a/src/main/java/subway/dao/SectionDao.java +++ b/src/main/java/subway/line/dao/SectionDao.java @@ -1,4 +1,4 @@ -package subway.dao; +package subway.line.dao; import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; diff --git a/src/main/java/subway/dao/SectionEntity.java b/src/main/java/subway/line/dao/SectionEntity.java similarity index 85% rename from src/main/java/subway/dao/SectionEntity.java rename to src/main/java/subway/line/dao/SectionEntity.java index 395827e0d..967bb6c47 100644 --- a/src/main/java/subway/dao/SectionEntity.java +++ b/src/main/java/subway/line/dao/SectionEntity.java @@ -1,12 +1,12 @@ -package subway.dao; +package subway.line.dao; public class SectionEntity { - private Long id; - private String currentStationName; - private String nextStationName; - private int distance; - private Long lineId; + private final Long id; + private final String currentStationName; + private final String nextStationName; + private final int distance; + private final Long lineId; public SectionEntity( final Long id, final String currentStationName, diff --git a/src/main/java/subway/domain/line/Line.java b/src/main/java/subway/line/domain/Line.java similarity index 97% rename from src/main/java/subway/domain/line/Line.java rename to src/main/java/subway/line/domain/Line.java index be8b8b843..a3f6fd037 100644 --- a/src/main/java/subway/domain/line/Line.java +++ b/src/main/java/subway/line/domain/Line.java @@ -1,10 +1,8 @@ -package subway.domain.line; +package subway.line.domain; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import subway.domain.section.Section; -import subway.domain.station.Station; public class Line { diff --git a/src/main/java/subway/domain/section/Section.java b/src/main/java/subway/line/domain/Section.java similarity index 97% rename from src/main/java/subway/domain/section/Section.java rename to src/main/java/subway/line/domain/Section.java index ab1130b68..f4111f050 100644 --- a/src/main/java/subway/domain/section/Section.java +++ b/src/main/java/subway/line/domain/Section.java @@ -1,8 +1,6 @@ -package subway.domain.section; +package subway.line.domain; import java.util.Objects; -import subway.domain.station.Station; -import subway.domain.station.Stations; public class Section { diff --git a/src/main/java/subway/domain/station/Station.java b/src/main/java/subway/line/domain/Station.java similarity index 96% rename from src/main/java/subway/domain/station/Station.java rename to src/main/java/subway/line/domain/Station.java index 515399b02..22e70cbcf 100644 --- a/src/main/java/subway/domain/station/Station.java +++ b/src/main/java/subway/line/domain/Station.java @@ -1,4 +1,4 @@ -package subway.domain.station; +package subway.line.domain; import java.util.Objects; diff --git a/src/main/java/subway/domain/station/Stations.java b/src/main/java/subway/line/domain/Stations.java similarity index 95% rename from src/main/java/subway/domain/station/Stations.java rename to src/main/java/subway/line/domain/Stations.java index 9d18a72c6..982fdf5f2 100644 --- a/src/main/java/subway/domain/station/Stations.java +++ b/src/main/java/subway/line/domain/Stations.java @@ -1,6 +1,6 @@ -package subway.domain.station; +package subway.line.domain; -import subway.domain.Distance; +import subway.value_object.Distance; public class Stations { diff --git a/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java b/src/main/java/subway/line/exception/CanNotDuplicatedLineNameException.java similarity index 74% rename from src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java rename to src/main/java/subway/line/exception/CanNotDuplicatedLineNameException.java index ab1e0509e..f7bb226d3 100644 --- a/src/main/java/subway/exception/line/CanNotDuplicatedLineNameException.java +++ b/src/main/java/subway/line/exception/CanNotDuplicatedLineNameException.java @@ -1,7 +1,7 @@ -package subway.exception.line; +package subway.line.exception; import org.springframework.http.HttpStatus; -import subway.exception.common.BusinessException; +import subway.exception.BusinessException; public class CanNotDuplicatedLineNameException extends BusinessException { diff --git a/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java b/src/main/java/subway/line/exception/CanNotDuplicatedSectionException.java similarity index 73% rename from src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java rename to src/main/java/subway/line/exception/CanNotDuplicatedSectionException.java index be955cc7f..8ca7c9579 100644 --- a/src/main/java/subway/exception/section/CanNotDuplicatedSectionException.java +++ b/src/main/java/subway/line/exception/CanNotDuplicatedSectionException.java @@ -1,7 +1,7 @@ -package subway.exception.section; +package subway.line.exception; import org.springframework.http.HttpStatus; -import subway.exception.common.BusinessException; +import subway.exception.BusinessException; public class CanNotDuplicatedSectionException extends BusinessException { diff --git a/src/main/java/subway/exception/line/CanNotFoundLineException.java b/src/main/java/subway/line/exception/CanNotFoundLineException.java similarity index 73% rename from src/main/java/subway/exception/line/CanNotFoundLineException.java rename to src/main/java/subway/line/exception/CanNotFoundLineException.java index 82b76996f..96659eda0 100644 --- a/src/main/java/subway/exception/line/CanNotFoundLineException.java +++ b/src/main/java/subway/line/exception/CanNotFoundLineException.java @@ -1,7 +1,7 @@ -package subway.exception.line; +package subway.line.exception; import org.springframework.http.HttpStatus; -import subway.exception.common.BusinessException; +import subway.exception.BusinessException; public class CanNotFoundLineException extends BusinessException { diff --git a/src/main/java/subway/controller/LineController.java b/src/main/java/subway/line/presentation/LineController.java similarity index 88% rename from src/main/java/subway/controller/LineController.java rename to src/main/java/subway/line/presentation/LineController.java index 9f44f0106..112c0252e 100644 --- a/src/main/java/subway/controller/LineController.java +++ b/src/main/java/subway/line/presentation/LineController.java @@ -1,4 +1,4 @@ -package subway.controller; +package subway.line.presentation; import java.util.List; import java.util.stream.Collectors; @@ -10,12 +10,12 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import subway.domain.line.Line; -import subway.service.LineCommandService; -import subway.service.LineQueryService; -import subway.service.dto.LineResponse; -import subway.service.dto.RegisterLineRequest; -import subway.service.dto.SectionResponse; +import subway.line.domain.Line; +import subway.line.application.LineCommandService; +import subway.line.application.LineQueryService; +import subway.line.application.dto.LineResponse; +import subway.line.application.dto.RegisterLineRequest; +import subway.line.application.dto.SectionResponse; @RestController public class LineController { diff --git a/src/main/java/subway/controller/StationController.java b/src/main/java/subway/line/presentation/StationController.java similarity index 82% rename from src/main/java/subway/controller/StationController.java rename to src/main/java/subway/line/presentation/StationController.java index 431336f5a..05bef2e30 100644 --- a/src/main/java/subway/controller/StationController.java +++ b/src/main/java/subway/line/presentation/StationController.java @@ -1,4 +1,4 @@ -package subway.controller; +package subway.line.presentation; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; @@ -6,10 +6,10 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import subway.service.StationService; -import subway.service.dto.StationDeleteRequest; -import subway.service.dto.StationRegisterRequest; -import subway.service.dto.StationRegisterResponse; +import subway.line.application.StationService; +import subway.line.application.dto.StationDeleteRequest; +import subway.line.application.dto.StationRegisterRequest; +import subway.line.application.dto.StationRegisterResponse; @RestController public class StationController { diff --git a/src/main/java/subway/domain/policy/ChargePolicyComposite.java b/src/main/java/subway/policy/application/ChargePolicyComposite.java similarity index 77% rename from src/main/java/subway/domain/policy/ChargePolicyComposite.java rename to src/main/java/subway/policy/application/ChargePolicyComposite.java index 7365558e6..755fd4536 100644 --- a/src/main/java/subway/domain/policy/ChargePolicyComposite.java +++ b/src/main/java/subway/policy/application/ChargePolicyComposite.java @@ -1,12 +1,12 @@ -package subway.domain.policy; +package subway.policy.application; import java.util.List; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.policy.discount.DiscountCondition; -import subway.domain.policy.discount.SubwayDiscountPolicy; -import subway.domain.policy.fare.SubwayFarePolicy; -import subway.domain.station.Station; +import subway.value_object.Money; +import subway.line.domain.Line; +import subway.policy.infrastructure.DiscountCondition; +import subway.policy.domain.SubwayDiscountPolicy; +import subway.policy.domain.SubwayFarePolicy; +import subway.line.domain.Station; public class ChargePolicyComposite implements SubwayFarePolicy, SubwayDiscountPolicy { diff --git a/src/main/java/subway/domain/policy/discount/AgeGroup.java b/src/main/java/subway/policy/domain/AgeGroup.java similarity index 93% rename from src/main/java/subway/domain/policy/discount/AgeGroup.java rename to src/main/java/subway/policy/domain/AgeGroup.java index ba85ee2e6..8283a04cc 100644 --- a/src/main/java/subway/domain/policy/discount/AgeGroup.java +++ b/src/main/java/subway/policy/domain/AgeGroup.java @@ -1,4 +1,4 @@ -package subway.domain.policy.discount; +package subway.policy.domain; import java.util.Arrays; import java.util.Objects; diff --git a/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java b/src/main/java/subway/policy/domain/SubwayDiscountPolicy.java similarity index 51% rename from src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java rename to src/main/java/subway/policy/domain/SubwayDiscountPolicy.java index db76f8709..ab1f86a0a 100644 --- a/src/main/java/subway/domain/policy/discount/SubwayDiscountPolicy.java +++ b/src/main/java/subway/policy/domain/SubwayDiscountPolicy.java @@ -1,6 +1,7 @@ -package subway.domain.policy.discount; +package subway.policy.domain; -import subway.domain.Money; +import subway.policy.infrastructure.DiscountCondition; +import subway.value_object.Money; public interface SubwayDiscountPolicy { diff --git a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java b/src/main/java/subway/policy/domain/SubwayFarePolicy.java similarity index 53% rename from src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java rename to src/main/java/subway/policy/domain/SubwayFarePolicy.java index cae162cce..6f8c4f567 100644 --- a/src/main/java/subway/domain/policy/fare/SubwayFarePolicy.java +++ b/src/main/java/subway/policy/domain/SubwayFarePolicy.java @@ -1,9 +1,9 @@ -package subway.domain.policy.fare; +package subway.policy.domain; import java.util.List; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.station.Station; +import subway.value_object.Money; +import subway.line.domain.Line; +import subway.line.domain.Station; public interface SubwayFarePolicy { diff --git a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java b/src/main/java/subway/policy/infrastructure/AgeDiscountPolicy.java similarity index 88% rename from src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java rename to src/main/java/subway/policy/infrastructure/AgeDiscountPolicy.java index 1e87049ee..05fd1cf51 100644 --- a/src/main/java/subway/domain/policy/discount/AgeDiscountPolicy.java +++ b/src/main/java/subway/policy/infrastructure/AgeDiscountPolicy.java @@ -1,8 +1,10 @@ -package subway.domain.policy.discount; +package subway.policy.infrastructure; import java.util.EnumMap; import java.util.Map; -import subway.domain.Money; +import subway.policy.domain.AgeGroup; +import subway.policy.domain.SubwayDiscountPolicy; +import subway.value_object.Money; public class AgeDiscountPolicy implements SubwayDiscountPolicy { diff --git a/src/main/java/subway/domain/policy/discount/DiscountCondition.java b/src/main/java/subway/policy/infrastructure/DiscountCondition.java similarity index 82% rename from src/main/java/subway/domain/policy/discount/DiscountCondition.java rename to src/main/java/subway/policy/infrastructure/DiscountCondition.java index 7226b7386..bcee91956 100644 --- a/src/main/java/subway/domain/policy/discount/DiscountCondition.java +++ b/src/main/java/subway/policy/infrastructure/DiscountCondition.java @@ -1,4 +1,4 @@ -package subway.domain.policy.discount; +package subway.policy.infrastructure; public class DiscountCondition { diff --git a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java b/src/main/java/subway/policy/infrastructure/DistanceFarePolicy.java similarity index 78% rename from src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java rename to src/main/java/subway/policy/infrastructure/DistanceFarePolicy.java index 1c2a57d87..38f381c16 100644 --- a/src/main/java/subway/domain/policy/fare/DistanceFarePolicy.java +++ b/src/main/java/subway/policy/infrastructure/DistanceFarePolicy.java @@ -1,15 +1,16 @@ -package subway.domain.policy.fare; +package subway.policy.infrastructure; -import static subway.domain.Distance.DEFAULT_DISTANCE; -import static subway.domain.Distance.MID_DISTANCE; +import static subway.value_object.Distance.DEFAULT_DISTANCE; +import static subway.value_object.Distance.MID_DISTANCE; import java.math.BigDecimal; import java.util.List; -import subway.domain.Distance; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.route.JgraphtRouteFinder; -import subway.domain.station.Station; +import subway.policy.domain.SubwayFarePolicy; +import subway.value_object.Distance; +import subway.value_object.Money; +import subway.line.domain.Line; +import subway.route.application.JgraphtRouteFinder; +import subway.line.domain.Station; public class DistanceFarePolicy implements SubwayFarePolicy { diff --git a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java b/src/main/java/subway/policy/infrastructure/LineFarePolicy.java similarity index 70% rename from src/main/java/subway/domain/policy/fare/LineFarePolicy.java rename to src/main/java/subway/policy/infrastructure/LineFarePolicy.java index 0ae47315a..cd4d2644d 100644 --- a/src/main/java/subway/domain/policy/fare/LineFarePolicy.java +++ b/src/main/java/subway/policy/infrastructure/LineFarePolicy.java @@ -1,12 +1,13 @@ -package subway.domain.policy.fare; +package subway.policy.infrastructure; import java.util.List; import java.util.Map; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.route.EdgeSection; -import subway.domain.route.JgraphtRouteFinder; -import subway.domain.station.Station; +import subway.policy.domain.SubwayFarePolicy; +import subway.value_object.Money; +import subway.line.domain.Line; +import subway.route.infrastructure.EdgeSection; +import subway.route.application.JgraphtRouteFinder; +import subway.line.domain.Station; public class LineFarePolicy implements SubwayFarePolicy { diff --git a/src/main/java/subway/domain/route/JgraphtRouteFinder.java b/src/main/java/subway/route/application/JgraphtRouteFinder.java similarity index 78% rename from src/main/java/subway/domain/route/JgraphtRouteFinder.java rename to src/main/java/subway/route/application/JgraphtRouteFinder.java index 825bb210a..af8b26260 100644 --- a/src/main/java/subway/domain/route/JgraphtRouteFinder.java +++ b/src/main/java/subway/route/application/JgraphtRouteFinder.java @@ -1,9 +1,11 @@ -package subway.domain.route; +package subway.route.application; import java.util.List; -import subway.domain.Distance; -import subway.domain.line.Line; -import subway.domain.station.Station; +import subway.value_object.Distance; +import subway.line.domain.Line; +import subway.line.domain.Station; +import subway.route.infrastructure.DijkstraGraphFactory; +import subway.route.infrastructure.EdgeSection; public class JgraphtRouteFinder { diff --git a/src/main/java/subway/service/RouteQueryService.java b/src/main/java/subway/route/application/RouteQueryService.java similarity index 81% rename from src/main/java/subway/service/RouteQueryService.java rename to src/main/java/subway/route/application/RouteQueryService.java index 4dd1af64d..a667bab45 100644 --- a/src/main/java/subway/service/RouteQueryService.java +++ b/src/main/java/subway/route/application/RouteQueryService.java @@ -1,17 +1,17 @@ -package subway.service; +package subway.route.application; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.policy.ChargePolicyComposite; -import subway.domain.policy.discount.DiscountCondition; -import subway.domain.route.JgraphtRouteFinder; -import subway.domain.station.Station; -import subway.service.dto.ShortestRouteRequest; -import subway.service.dto.ShortestRouteResponse; +import subway.value_object.Money; +import subway.line.application.LineQueryService; +import subway.line.domain.Line; +import subway.policy.application.ChargePolicyComposite; +import subway.policy.infrastructure.DiscountCondition; +import subway.line.domain.Station; +import subway.route.application.dto.ShortestRouteRequest; +import subway.route.application.dto.ShortestRouteResponse; @Service @Transactional(readOnly = true) diff --git a/src/main/java/subway/service/dto/ShortestRouteRequest.java b/src/main/java/subway/route/application/dto/ShortestRouteRequest.java similarity index 93% rename from src/main/java/subway/service/dto/ShortestRouteRequest.java rename to src/main/java/subway/route/application/dto/ShortestRouteRequest.java index 7ee988d1b..158ff5a08 100644 --- a/src/main/java/subway/service/dto/ShortestRouteRequest.java +++ b/src/main/java/subway/route/application/dto/ShortestRouteRequest.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.route.application.dto; public class ShortestRouteRequest { diff --git a/src/main/java/subway/service/dto/ShortestRouteResponse.java b/src/main/java/subway/route/application/dto/ShortestRouteResponse.java similarity index 93% rename from src/main/java/subway/service/dto/ShortestRouteResponse.java rename to src/main/java/subway/route/application/dto/ShortestRouteResponse.java index 9fb3ab87f..275ea177f 100644 --- a/src/main/java/subway/service/dto/ShortestRouteResponse.java +++ b/src/main/java/subway/route/application/dto/ShortestRouteResponse.java @@ -1,4 +1,4 @@ -package subway.service.dto; +package subway.route.application.dto; import java.util.List; diff --git a/src/main/java/subway/domain/route/DijkstraGraphFactory.java b/src/main/java/subway/route/infrastructure/DijkstraGraphFactory.java similarity index 90% rename from src/main/java/subway/domain/route/DijkstraGraphFactory.java rename to src/main/java/subway/route/infrastructure/DijkstraGraphFactory.java index 69c216e51..0cf536e27 100644 --- a/src/main/java/subway/domain/route/DijkstraGraphFactory.java +++ b/src/main/java/subway/route/infrastructure/DijkstraGraphFactory.java @@ -1,13 +1,13 @@ -package subway.domain.route; +package subway.route.infrastructure; import java.util.List; import org.jgrapht.Graph; import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.graph.WeightedMultigraph; -import subway.domain.line.Line; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; +import subway.line.domain.Line; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; public class DijkstraGraphFactory { @@ -15,7 +15,8 @@ private DijkstraGraphFactory() { } public static DijkstraShortestPath makeDijkstraGraph( - final List lines) { + final List lines + ) { Graph graph = new WeightedMultigraph<>(EdgeSection.class); diff --git a/src/main/java/subway/domain/route/EdgeSection.java b/src/main/java/subway/route/infrastructure/EdgeSection.java similarity index 95% rename from src/main/java/subway/domain/route/EdgeSection.java rename to src/main/java/subway/route/infrastructure/EdgeSection.java index 4e2db4417..0496d6502 100644 --- a/src/main/java/subway/domain/route/EdgeSection.java +++ b/src/main/java/subway/route/infrastructure/EdgeSection.java @@ -1,4 +1,4 @@ -package subway.domain.route; +package subway.route.infrastructure; import org.jgrapht.graph.DefaultWeightedEdge; diff --git a/src/main/java/subway/controller/RouteController.java b/src/main/java/subway/route/presentation/RouteController.java similarity index 75% rename from src/main/java/subway/controller/RouteController.java rename to src/main/java/subway/route/presentation/RouteController.java index 02460235b..a99637f18 100644 --- a/src/main/java/subway/controller/RouteController.java +++ b/src/main/java/subway/route/presentation/RouteController.java @@ -1,11 +1,11 @@ -package subway.controller; +package subway.route.presentation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RestController; -import subway.service.RouteQueryService; -import subway.service.dto.ShortestRouteRequest; -import subway.service.dto.ShortestRouteResponse; +import subway.route.application.RouteQueryService; +import subway.route.application.dto.ShortestRouteRequest; +import subway.route.application.dto.ShortestRouteResponse; @RestController public class RouteController { diff --git a/src/main/java/subway/service/dto/LeastCostRouteResponse.java b/src/main/java/subway/service/dto/LeastCostRouteResponse.java deleted file mode 100644 index 6d5a107d7..000000000 --- a/src/main/java/subway/service/dto/LeastCostRouteResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package subway.service.dto; - -public class LeastCostRouteResponse { - - private final String startStation; - private final String endStation; - private final int cost; - private final int distance; - - public LeastCostRouteResponse( - final String startStation, - final String endStation, - final int cost, - final int distance - ) { - this.startStation = startStation; - this.endStation = endStation; - this.cost = cost; - this.distance = distance; - } - - public String getStartStation() { - return startStation; - } - - public String getEndStation() { - return endStation; - } - - public int getCost() { - return cost; - } - - public int getDistance() { - return distance; - } -} diff --git a/src/main/java/subway/domain/Distance.java b/src/main/java/subway/value_object/Distance.java similarity index 98% rename from src/main/java/subway/domain/Distance.java rename to src/main/java/subway/value_object/Distance.java index c68fac433..5e12923db 100644 --- a/src/main/java/subway/domain/Distance.java +++ b/src/main/java/subway/value_object/Distance.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.value_object; import java.util.Objects; diff --git a/src/main/java/subway/domain/Money.java b/src/main/java/subway/value_object/Money.java similarity index 98% rename from src/main/java/subway/domain/Money.java rename to src/main/java/subway/value_object/Money.java index c106485e3..33a7d0cf1 100644 --- a/src/main/java/subway/domain/Money.java +++ b/src/main/java/subway/value_object/Money.java @@ -1,4 +1,4 @@ -package subway.domain; +package subway.value_object; import java.math.BigDecimal; import java.math.RoundingMode; diff --git a/src/test/java/helper/IntegrationTestHelper.java b/src/test/java/helper/IntegrationTestHelper.java index 0b6230f76..ff78e2e2a 100644 --- a/src/test/java/helper/IntegrationTestHelper.java +++ b/src/test/java/helper/IntegrationTestHelper.java @@ -10,4 +10,5 @@ @Sql(value = "/schema.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(value = "/data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) public class IntegrationTestHelper { + } diff --git a/src/test/java/subway/controller/LineControllerTest.java b/src/test/java/subway/controller/LineControllerTest.java deleted file mode 100644 index 74742b868..000000000 --- a/src/test/java/subway/controller/LineControllerTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package subway.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import subway.domain.line.Line; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; -import subway.service.LineCommandService; -import subway.service.LineQueryService; -import subway.service.dto.RegisterLineRequest; - -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@WebMvcTest(LineController.class) -class LineControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private LineCommandService lineCommandService; - - @MockBean - private LineQueryService lineQueryService; - - @Test - @DisplayName("showLines() : lineName이 주어지면 해당 line을 성공적으로 조회할 때 200 OK을 반환한다.") - void test_showLines() throws Exception { - //given - final String lineName = "2호선"; - - final List lines = createDefaultLines(); - - when(lineQueryService.searchLines(any())) - .thenReturn(lines); - - //when & then - mockMvc.perform(get("/lines?lineName={lineName}", lineName)) - .andExpect(status().isOk()); - } - - @Test - @DisplayName("showLines() : lineName이 주어지지 않으면 모든 line을 성공적으로 조회할 때 200 OK을 반환한다.") - void test_showLines_all() throws Exception { - //given - final List lines = createDefaultLines(); - - when(lineQueryService.searchLines(any())) - .thenReturn(lines); - - //when & then - mockMvc.perform(get("/lines")) - .andExpect(status().isOk()); - } - - @Test - @DisplayName("showLine() : id를 통해 해당 Line을 성공적으로 조회할 때 200 OK을 반환한다.") - void test_showLine() throws Exception { - //given - final List lines = createDefaultLines(); - final long lineId = 1L; - - when(lineQueryService.searchByLineId(anyLong())) - .thenReturn(lines.get(0)); - - //when & then - mockMvc.perform(get("/lines/{line-id}", lineId)) - .andExpect(status().isOk()); - } - - @Test - @DisplayName("registerLine() : Line을 성공적으로 저장할 때 201 Created를 반환한다.") - void test_registerLine() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "B"; - final String lineName = "line"; - final int distance = 4; - - final RegisterLineRequest registerLineRequest = - new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); - - final String bodyData = objectMapper.writeValueAsString(registerLineRequest); - - doNothing().when(lineCommandService) - .registerLine(any()); - - when(lineQueryService.searchByLineName(any())) - .thenReturn(createDefaultLines().get(0)); - - //when & then - mockMvc.perform(post("/lines") - .contentType(MediaType.APPLICATION_JSON) - .content(bodyData)) - .andExpect(status().isCreated()); - } - - private List createDefaultLines() { - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section section1 = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); - - final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); - final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); - final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); - final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); - - final Section section4 = new Section(stations4); - final Section section5 = new Section(stations5); - final Section section6 = new Section(stations6); - final Section section7 = new Section(stations7); - - final Line line2 = new Line(2L, "2호선", - List.of(section4, section5, section6, section7)); - - return List.of(line1, line2); - } -} diff --git a/src/test/java/subway/controller/StationControllerTest.java b/src/test/java/subway/controller/StationControllerTest.java deleted file mode 100644 index a1333188d..000000000 --- a/src/test/java/subway/controller/StationControllerTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package subway.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import subway.service.StationService; -import subway.service.dto.StationDeleteRequest; -import subway.service.dto.StationRegisterRequest; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@WebMvcTest(StationController.class) -class StationControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private StationService stationService; - - @Autowired - private ObjectMapper objectMapper; - - @Test - @DisplayName("registerStation() : station이 정상적으로 저장되면 201 Created를 반환한다.") - void test_registerStation() throws Exception { - //given - final String currentStationName = "A"; - final String nextStationName = "B"; - final String lineName = "line"; - final int distance = 4; - - final StationRegisterRequest stationRegisterRequest = - new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); - - final String bodyData = objectMapper.writeValueAsString(stationRegisterRequest); - - doNothing().when(stationService) - .registerStation(any()); - - //when & then - mockMvc.perform(post("/stations") - .contentType(MediaType.APPLICATION_JSON) - .content(bodyData)) - .andExpect(status().isCreated()); - } - - @Test - @DisplayName("deleteStation() : station 이 정상적으로 삭제되면 204 No Content 를 반환한다.") - void test_deleteStation() throws Exception { - //given - final String lineName = "line"; - final String stationName = "station"; - - final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName); - - final String bodyData = objectMapper.writeValueAsString(stationDeleteRequest); - - doNothing().when(stationService) - .deleteStation(any()); - - //when & then - mockMvc.perform(delete("/stations") - .contentType(MediaType.APPLICATION_JSON) - .content(bodyData)) - .andExpect(status().isNoContent()); - } -} diff --git a/src/test/java/subway/dao/LineDaoTest.java b/src/test/java/subway/dao/LineDaoTest.java deleted file mode 100644 index 8328749aa..000000000 --- a/src/test/java/subway/dao/LineDaoTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package subway.dao; - -import org.assertj.core.api.Assertions; -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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; -import org.springframework.jdbc.core.JdbcTemplate; - -import java.util.List; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - -@JdbcTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class LineDaoTest { - - @Autowired - private JdbcTemplate jdbcTemplate; - - private LineDao lineDao; - - @BeforeEach - void setUp() { - lineDao = new LineDao(jdbcTemplate); - } - - @Test - @DisplayName("findByLineName() : 라인 이름으로 라인을 찾을 수 있다.") - void test_findByLineName() throws Exception { - //given - final String lineName = "1호선"; - - //when - final Optional savedLine = lineDao.findByLineName(lineName); - - //then - assertAll( - () -> assertThat(savedLine).isPresent(), - () -> assertEquals(1L, savedLine.get().getId()), - () -> assertEquals(savedLine.get().getName(), lineName) - ); - } - - @Test - @DisplayName("findAll() : 모든 라인을 찾을 수 있다.") - void test_findAll() throws Exception { - //when - final List lineEntities = lineDao.findAll(); - - //then - assertEquals(2, lineEntities.size()); - } - - @Test - @DisplayName("findByLineId() : 라인 id로 라인을 찾을 수 있다.") - void test_findByLineId() throws Exception { - //given - final Long lineId = 2L; - - //when - final Optional savedLine = lineDao.findByLineId(lineId); - - //then - assertAll( - () -> Assertions.assertThat(savedLine).isPresent(), - () -> assertEquals(2L, savedLine.get().getId()), - () -> assertEquals("2호선", savedLine.get().getName()) - ); - } - - @Test - @DisplayName("deleteById() : 라인 id로 라인을 삭제할 수 있다.") - void test_deleteById() throws Exception { - //given - final Long lineId = 2L; - - final int beforeSize = lineDao.findAll().size(); - - //when - lineDao.deleteById(lineId); - - //then - final int afterSize = lineDao.findAll().size(); - assertEquals(afterSize, beforeSize - 1); - } - - @Test - @DisplayName("save() : 라인을 저장할 수 있다.") - void test_save() throws Exception { - //given - final LineEntity lineEntity = new LineEntity("newLine"); - - final int beforeSize = lineDao.findAll().size(); - - //when - lineDao.save(lineEntity); - - //then - final int afterSize = lineDao.findAll().size(); - - assertEquals(afterSize, beforeSize + 1); - } -} diff --git a/src/test/java/subway/dao/SectionDaoTest.java b/src/test/java/subway/dao/SectionDaoTest.java deleted file mode 100644 index 53507ed92..000000000 --- a/src/test/java/subway/dao/SectionDaoTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package subway.dao; - -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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; -import org.springframework.jdbc.core.JdbcTemplate; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - -@JdbcTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class SectionDaoTest { - - @Autowired - private JdbcTemplate jdbcTemplate; - - private SectionDao sectionDao; - - @BeforeEach - void setUp() { - sectionDao = new SectionDao(jdbcTemplate); - } - - @Test - @DisplayName("save() : section을 저장할 수 있다.") - void test_save() throws Exception { - //given - final String currentStationName = "H"; - final String nextStationName = "Z"; - final int distance = 1; - final long lineId = 2L; - - final SectionEntity sectionEntity = new SectionEntity( - currentStationName, - nextStationName, - distance, - lineId - ); - - final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); - - //when - sectionDao.save(sectionEntity); - - //then - final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); - - assertEquals(afterSize, beforeSize + 1); - } - - @Test - @DisplayName("findSectionsByLineId() : 라인에 속한 모든 section을 조회할 수 있다.") - void test_findSectionsByLineId() throws Exception { - //given - final long lineId = 2L; - - //when - final int size = sectionDao.findSectionsByLineId(lineId).size(); - - //then - assertEquals(4, size); - } - - @Test - @DisplayName("deleteAll() : 라인에 포함되있는 section을 모두 삭제할 수 있다.") - void test_deleteAll() throws Exception { - //given - final long lineId = 2L; - - //when - sectionDao.deleteAll(lineId); - - //then - assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); - } - - @Test - @DisplayName("update() : id를 통해 세션의 정보를 수정할 수 있다.") - void test_update() throws Exception { - //given - final Long sectionId = 7L; - final String updatedCurrentStationName = "Z"; - final String updatedNextStationName = "K"; - final int updatedDistance = 3; - final long lineId = 2L; - - final SectionEntity updatedSectionEntity = new SectionEntity( - 7L, - updatedCurrentStationName, - updatedNextStationName, - updatedDistance, - lineId - ); - - //when - sectionDao.update(updatedSectionEntity); - - //then - final SectionEntity sectionEntity = - sectionDao.findSectionsByLineId(lineId) - .stream() - .filter(it -> it.getId().equals(sectionId)) - .findAny() - .orElseThrow(); - - assertAll( - () -> assertEquals(sectionEntity.getDistance(), updatedSectionEntity.getDistance()), - () -> assertEquals(sectionEntity.getCurrentStationName(), - updatedSectionEntity.getCurrentStationName()), - () -> assertEquals(sectionEntity.getNextStationName(), - updatedSectionEntity.getNextStationName()) - ); - } - - @Test - @DisplayName("deleteById() : id를 통해 section을 삭제할 수 있다.") - void test_deleteById() throws Exception { - //given - final long sectionId = 1L; - final long lineId = 1L; - - final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); - - //when - sectionDao.deleteById(sectionId); - - //then - final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); - - assertEquals(afterSize, beforeSize - 1); - } -} diff --git a/src/test/java/subway/domain/MoneyTest.java b/src/test/java/subway/domain/MoneyTest.java deleted file mode 100644 index 37be7beb7..000000000 --- a/src/test/java/subway/domain/MoneyTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package subway.domain; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertEquals; - -class MoneyTest { - - @ParameterizedTest - @CsvSource({ - "10000, 35, 6500", - "1000, 10, 900", - "3500, 10, 3150" - }) - @DisplayName("discountPercent() : 할인을 받고 난 금액을 계산할 수 있다.") - void test_discountPercent(final int origin, final int percent, final int result) throws Exception { - //given - final Money originMoney = new Money(origin); - final Money resultMoney = new Money(result); - - //when & then - assertEquals(resultMoney, originMoney.calculateDiscountedPrice(percent)); - } - - @Test - @DisplayName("constructor() : 돈이 음수가 되면 IllegalArgumentException가 발생합니다.") - void test_constructor_IllegalArgumentException() throws Exception { - //when & then - assertThatThrownBy(() -> new Money(-1)) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - @DisplayName("discountPercent() : 할인율이 0퍼센트이면 그대로 값을 반환합니다.") - void test_discountPercent_zeroPercent() throws Exception { - //given - final Money money = new Money(10000); - final int percentage = 0; - - //when & then - assertEquals(money, money.calculateDiscountedPrice(percentage)); - } -} diff --git a/src/test/java/subway/domain/line/LineTest.java b/src/test/java/subway/domain/line/LineTest.java deleted file mode 100644 index c16d338aa..000000000 --- a/src/test/java/subway/domain/line/LineTest.java +++ /dev/null @@ -1,279 +0,0 @@ -package subway.domain.line; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class LineTest { - - /** - * 기존 : A -> B - * 추가 : B -> C - * 결과 : A -> B -> C - */ - @Test - @DisplayName("add() : Line의 맨 끝에 새로운 섹션을 추가할 수 있다.") - void test_add_last() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - - Section 출발_섹션 = new Section(stations1); - final Line line = new Line(1L, "2호선", List.of(출발_섹션)); - - final Section newSection = new Section(stations2); - - //when - line.add(newSection); - - //then - assertAll( - () -> assertEquals(line.getStarter(), 출발_섹션), - () -> assertEquals(line.getStarter().getTo(), newSection) - ); - } - - /** - * 기존 : `A` -> B -> C -> D -> E - * 추가 : D -> F - * 결론 : `A` -> B -> C -> D -> F -> E - */ - @Test - @DisplayName("add() : Line의 중간에 새로운 섹션을 추가할 수 있다.") - void test_add_intermediate() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 헤드_섹션 = new Section(stations1); - - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - final Section section4 = new Section(stations4); - - final Line line = new Line(1L, "2호선", List.of(헤드_섹션, section2, section3, section4)); - - final Station current = new Station("D"); - final Station next = new Station("F"); - - final Stations 새로운_stations = new Stations(current, next, 2); - - final Section 새로운_섹션 = new Section(새로운_stations); - - //when - line.add(새로운_섹션); - - //then - assertEquals(section3.getTo(), 새로운_섹션); - } - - /** - * 기존 : `A` -> B -> C -> D -> E - * 추가 : A -> K - * 결론 : `A` -> K -> B -> C -> D -> E - */ - @Test - @DisplayName("add() : Line의 중간에 새로운 섹션을 추가할 수 있다.") - void test_add_intermediate2() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 헤드_섹션 = new Section(stations1); - - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - final Section section4 = new Section(stations4); - - final Line line = new Line(1L, "2호선", List.of(헤드_섹션, section2, section3, section4)); - - final Station current = new Station("A"); - final Station next = new Station("K"); - - final Stations 새로운_stations = new Stations(current, next, 2); - - final Section 새로운_섹션 = new Section(새로운_stations); - - //when - line.add(새로운_섹션); - - //then - assertAll( - () -> assertEquals(헤드_섹션.getTo(), section2), - () -> assertEquals(새로운_섹션.getTo(), 헤드_섹션), - () -> assertEquals(3, 헤드_섹션.getStations().getDistance()) - ); - } - - /** - * 기존 : A -> B -> C - * 추가 : Z -> A - * 결론 : Z -> A -> B -> C - */ - @Test - @DisplayName("add() : 새롭게 추가된 섹션이 Line의 새로운 Starter가 될 수 있다.") - void test_add_newStarter() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("Z"), new Station("A"), 4); - - Section 스타터_바뀔_예정_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - - final Line line = new Line(1L, "2호선", List.of(스타터_바뀔_예정_섹션, section2)); - - final Section 새로운_섹션 = new Section(stations3); - - //when - line.add(새로운_섹션); - - //then - assertAll( - () -> assertEquals(line.getStarter(), 새로운_섹션), - () -> assertEquals(새로운_섹션.getTo(), 스타터_바뀔_예정_섹션) - ); - } - - @Test - @DisplayName("add() : Line에 새롭게 추가되지 못하는 섹션을 넣을 경우 IllegalArgumentException이 발생할 수 있다.") - void test_add_IllegalArgumentException() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("B"), new Station("A"), 4); - - Section 스타터_바뀔_예정_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - - final Line line = new Line(1L, "2호선", List.of(스타터_바뀔_예정_섹션, section2)); - - final Section 새로운_섹션 = new Section(stations3); - - //when & then - assertThatThrownBy(() -> line.add(새로운_섹션)) - .isInstanceOf(IllegalArgumentException.class); - } - - - /** - * 기존 : A -> B -> C -> D - * 삭제 : B - * 결론 : A -> C -> D - */ - @Test - @DisplayName("delete() : Line 중간에 있는 Section을 삭제할 수 있다.") - void test_delete() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section starter = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); - - //when - line.delete(new Station("B")); - - //then - assertAll( - () -> assertEquals(starter.getTo(), section3), - () -> assertNull(section2.getTo()), - () -> assertEquals(9, starter.getStations().getDistance()), - () -> assertTrue(starter.getStations().getNext() - .isSame(section2.getStations().getNext())) - ); - } - - /** - * 기존 : A -> B -> C -> D - * 삭제 : A - * 결론 : B -> C -> D - */ - @Test - @DisplayName("delete() : Line의 starter를 삭제할 수 있다.") - void test_delete_starter() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section starter = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); - - //when - line.delete(new Station("A")); - - //then - assertAll( - () -> assertEquals(section2.getTo(), section3), - () -> assertEquals(line.getStarter(), section2), - () -> assertNull(starter.getTo()) - ); - } - - /** - * 기존 : A -> B -> C -> D - * 삭제 : D - * 결과 : A -> B -> C - */ - @Test - @DisplayName("delete() : Line의 마지막 역을 삭제할 수 있다.") - void test_delete_last_station() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - - final Section starter = new Section(stations1); - final Section section2 = new Section(stations2); - final Section section3 = new Section(stations3); - - final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); - - //when - line.delete(new Station("D")); - - //then - assertNull(section2.getTo()); - } - - /** - * 기존 : A -> B - * 삭제 : B - * 결과 : Line 삭제 - */ - @Test - @DisplayName("delete() : Line 에 Section 이 하나밖에 없을 때, 역을 삭제할 경우 Line이 사라진다.") - void test_delete_line() throws Exception { - //given - final Stations stations = new Stations(new Station("A"), new Station("B"), 5); - final Line line = new Line(1L, "2호선", List.of(new Section(stations))); - - //when - line.delete(new Station("B")); - - //then - assertNull(line.getStarter()); - } -} diff --git a/src/test/java/subway/domain/section/SectionTest.java b/src/test/java/subway/domain/section/SectionTest.java deleted file mode 100644 index 7247fa926..000000000 --- a/src/test/java/subway/domain/section/SectionTest.java +++ /dev/null @@ -1,191 +0,0 @@ -package subway.domain.section; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import subway.domain.station.Station; -import subway.domain.station.Stations; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class SectionTest { - - /** - * 기존 : A-B-C-D-E - * 추가 : D-F - * 결과 : IllegalArgumentException - */ - @Test - @DisplayName("addNext() : 중간에 끼어드는 섹션의 길이가 현재 연결된 섹션의 길이보다 크면 IllegalArgumentException가 발생한다.") - void test_addNext_IllegalArgumentException() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 시작_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - 시작_섹션.addNext(section2); - - final Section section3 = new Section(stations3); - 시작_섹션.addNext(section3); - - final Section section4 = new Section(stations4); - 시작_섹션.addNext(section4); - - final Station current = new Station("D"); - final Station next = new Station("F"); - - final Stations 새로운_stations = new Stations(current, next, 5); - - final Section 새로운_섹션 = new Section(새로운_stations); - - //when & then - assertThatThrownBy(() -> 시작_섹션.addNext(새로운_섹션)) - .isInstanceOf(IllegalArgumentException.class); - } - - /** - * 기존 : A-B-C-D-E - * 추가 : D-F - * 결과 : A-B-C-D-F-E - */ - @Test - @DisplayName("addNext() : 중간에 끼어드는 섹션의 길이가 현재 연결된 섹션의 길이보다 작으면 섹션을 추가할 수 있다.") - void test_addNext() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 시작_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - 시작_섹션.addNext(section2); - - final Section section3 = new Section(stations3); - 시작_섹션.addNext(section3); - - final Section section4 = new Section(stations4); - 시작_섹션.addNext(section4); - - final Station current = new Station("D"); - final Station next = new Station("F"); - - final Stations 새로운_stations = new Stations(current, next, 2); - - final Section 새로운_섹션 = new Section(새로운_stations); - - //when - 시작_섹션.addNext(새로운_섹션); - - //then - assertAll( - () -> assertEquals(section3.getTo(), 새로운_섹션), - () -> assertEquals(새로운_섹션.getTo(), section4), - () -> assertEquals(1, 새로운_섹션.getTo().getStations().getDistance() - ) - ); - } - - /** - * 기존 : A-B-C-D-E - * 추가 : E-F - * 결과 : A-B-C-D-E-F - */ - @Test - @DisplayName("addNext() : 새로운 섹션을 맨 마지막에 추가할 수 있다.") - void test_addNext_last() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 시작_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - 시작_섹션.addNext(section2); - - final Section section3 = new Section(stations3); - 시작_섹션.addNext(section3); - - final Section section4 = new Section(stations4); - 시작_섹션.addNext(section4); - - final Station current = new Station("E"); - final Station next = new Station("F"); - - final Stations 새로운_stations = new Stations(current, next, 2); - - final Section 새로운_섹션 = new Section(새로운_stations); - - //when - 시작_섹션.addNext(새로운_섹션); - - //then - assertAll( - () -> assertEquals(section4.getTo(), 새로운_섹션) - ); - } - - /** - * 기존 : A -> B - * 추가 : B -> C - * 결과 : A -> B -> C - */ - @Test - @DisplayName("isLinked() : 시작 섹션의 목적지와 도착 섹션의 출발지가 같으면 두 섹션은 연결될 수 있다.") - void test_isLinked() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - - final Section start = new Section(stations1); - final Section end = new Section(stations2); - - //when & then - assertTrue(end.isLinked(start)); - } - - /** - * 기존 : A-B-C-D-E - * 삭제 : C - * 결과 : A-B-D-E - */ - @Test - @DisplayName("delete() : 중간 섹션을 삭제할 수 있다.") - void test_delete() throws Exception { - //given - final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); - final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); - final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); - final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); - - Section 시작_섹션 = new Section(stations1); - final Section section2 = new Section(stations2); - 시작_섹션.addNext(section2); - - final Section section3 = new Section(stations3); - 시작_섹션.addNext(section3); - - final Section section4 = new Section(stations4); - 시작_섹션.addNext(section4); - - final Station 삭제할_역 = new Station("C"); - - //when - 시작_섹션.delete(삭제할_역); - - //then - assertAll( - () -> assertEquals(section2.getTo(), section4), - () -> assertNull(section3.getTo()), - () -> assertTrue(section2.getStations().getNext().isSame(section3.getStations().getNext())), - () -> assertEquals(7, section2.getStations().getDistance()) - ); - } -} diff --git a/src/test/java/subway/domain/station/StationTest.java b/src/test/java/subway/domain/station/StationTest.java deleted file mode 100644 index 5d717a4f8..000000000 --- a/src/test/java/subway/domain/station/StationTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package subway.domain.station; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -class StationTest { - - @Test - @DisplayName("isSame() : 이름이 같으면 같은 역이다.") - void test_isSame() throws Exception { - //given - final Station station1 = new Station("A"); - final Station station2 = new Station("A"); - - //when & then - assertTrue(station1.isSame(station2)); - } -} diff --git a/src/test/java/subway/domain/station/StationsTest.java b/src/test/java/subway/domain/station/StationsTest.java deleted file mode 100644 index 59fedce81..000000000 --- a/src/test/java/subway/domain/station/StationsTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package subway.domain.station; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -class StationsTest { - - @Test - @DisplayName("isLinked() : 두 역이 이어져있는지 확인할 수 있다.") - void test_isLinked() throws Exception { - //given - final Stations stations1 = new Stations( - new Station("A"), - new Station("B"), - 3 - ); - - final Stations stations2 = new Stations( - new Station("B"), - new Station("C"), - 4 - ); - - //when & then - assertTrue(stations1.isLinked(stations2)); - } -} diff --git a/src/test/java/subway/line/application/LineCommandServiceTest.java b/src/test/java/subway/line/application/LineCommandServiceTest.java new file mode 100644 index 000000000..05b8e7c6e --- /dev/null +++ b/src/test/java/subway/line/application/LineCommandServiceTest.java @@ -0,0 +1,78 @@ +package subway.line.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import helper.IntegrationTestHelper; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.line.application.dto.RegisterLineRequest; +import subway.line.dao.LineDao; +import subway.line.dao.LineEntity; +import subway.line.exception.CanNotDuplicatedLineNameException; + +class LineCommandServiceTest extends IntegrationTestHelper { + + @Autowired + private LineCommandService lineCommandService; + + @Autowired + private LineDao lineDao; + + @Test + @DisplayName("deleteLine() : line id 가 주어졌을 때 해당 라인을 삭제할 수 있다.") + void test_deleteLine() throws Exception { + //given + final long lineId = 1L; + + //when + lineCommandService.deleteLine(lineId); + + //then + final Optional savedLine = lineDao.findByLineId(lineId); + + assertThat(savedLine).isEmpty(); + } + + @Test + @DisplayName("registerLine() : 새로운 line을 생성할 수 있다.") + void test_registerLine() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final String lineName = "line"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + final int beforeSize = lineDao.findAll().size(); + + //when + lineCommandService.registerLine(registerLineRequest); + + //then + final int afterSize = lineDao.findAll().size(); + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("registerLine() : line을 새로 생성할 때, 기존에 있는 lineName이 존재한다면 CanNotDuplicatedLineNameException이 발생한다.") + void test_registerLine_CanNotDuplicatedLineNameException() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final String lineName = "1호선"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + //when & then + assertThatThrownBy(() -> lineCommandService.registerLine(registerLineRequest)) + .isInstanceOf(CanNotDuplicatedLineNameException.class); + } +} diff --git a/src/test/java/subway/line/application/LineQueryServiceTest.java b/src/test/java/subway/line/application/LineQueryServiceTest.java new file mode 100644 index 000000000..3cb1009a5 --- /dev/null +++ b/src/test/java/subway/line/application/LineQueryServiceTest.java @@ -0,0 +1,96 @@ +package subway.line.application; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import helper.IntegrationTestHelper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.springframework.beans.factory.annotation.Autowired; +import subway.line.domain.Line; + +class LineQueryServiceTest extends IntegrationTestHelper { + + @Autowired + private LineQueryService lineQueryService; + + @Test + @DisplayName("searchLines() : lineName이 존재하지 않으면 모든 line을 조회할 수 있다.") + void test_searchLines_all() throws Exception { + //given + final String lineName = null; + + //when + final List lines = lineQueryService.searchLines(lineName); + + //then + assertEquals(2, lines.size()); + } + + @Test + @DisplayName("searchLines() : lineName을 통해 해당 line을 조회할 수 있다.") + void test_searchLines() throws Exception { + //given + final String lineName = "1호선"; + + //when + final List lines = lineQueryService.searchLines(lineName); + + //then + assertAll( + () -> assertEquals(1, lines.size()), + () -> assertEquals(lines.get(0).getName(), lineName) + ); + } + + @Test + @DisplayName("searchAllLine() : 모든 Line을 조회할 수 있다.") + void test_searchAllLine() throws Exception { + //when + final List lines = lineQueryService.searchAllLine(); + + //then + assertEquals(2, lines.size()); + } + + @Test + @DisplayName("searchByLineName() : lineName을 통해 해당 line을 조회할 수 있다.") + void test_searchByLineName() throws Exception { + //given + final String lineName = "1호선"; + + //when + final Line line = lineQueryService.searchByLineName(lineName); + + //then + assertEquals(line.getName(), lineName); + } + + @Test + @DisplayName("searchByLineId() : line id를 통해 해당 line을 조회할 수 있다.") + void test_searchByLineId() throws Exception { + //given + final Long lineId = 1L; + + //when + final Line line = lineQueryService.searchByLineId(lineId); + + //then + assertEquals(line.getId(), lineId); + } + + @ParameterizedTest + @CsvSource({ + "1호선, true", + "2호선, true", + "3호선, false" + }) + @DisplayName("isExistLine() : lineName을 통해 해당 line이 존재하는지 알 수 있다.") + void test_isExistLine(final String lineName, final boolean isExist) throws Exception { + //then + assertEquals(isExist, lineQueryService.isExistLine(lineName)); + } +} diff --git a/src/test/java/subway/line/application/SectionCommandServiceTest.java b/src/test/java/subway/line/application/SectionCommandServiceTest.java new file mode 100644 index 000000000..9aff14625 --- /dev/null +++ b/src/test/java/subway/line/application/SectionCommandServiceTest.java @@ -0,0 +1,121 @@ +package subway.line.application; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.line.dao.SectionDao; +import subway.line.dao.SectionEntity; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; +import subway.line.exception.CanNotDuplicatedSectionException; + +class SectionCommandServiceTest extends IntegrationTestHelper { + + @Autowired + private SectionCommandService sectionCommandService; + + @Autowired + private SectionDao sectionDao; + + @Test + @DisplayName("registerSection() : 섹션을 저장할 수 있다.") + void test_registerSection() throws Exception { + //given + final String currentStationName = "D"; + final String nextStationName = "Z"; + final Long lineId = 2L; + final int distance = 4; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionCommandService.registerSection(currentStationName, nextStationName, distance, lineId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("registerSection() : 섹션을 저장할 때, 해당 호선에 같은 섹션이 있으면 CanNotDuplicatedSectionException이 발생한다.") + void test_registerSection_CanNotDuplicatedSectionException() throws Exception { + //given + final String currentStationName = "B"; + final String nextStationName = "F"; + final Long lineId = 2L; + final int distance = 4; + + //when & then + assertThatThrownBy( + () -> sectionCommandService.registerSection(currentStationName, nextStationName, distance, + lineId)) + .isInstanceOf(CanNotDuplicatedSectionException.class); + } + + @Test + @DisplayName("deleteAll() : 주어진 호선에 있는 섹션들을 모두 삭제할 수 있다.") + void test_deleteAll() throws Exception { + //given + final long lineId = 1L; + + //when + sectionCommandService.deleteAll(lineId); + + //then + assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); + } + + @Test + @DisplayName("deleteSection() : section id를 통해 섹션을 삭제할 수 있다.") + void test_deleteSection() throws Exception { + //given + final long sectionId = 1L; + final long lineId = 1L; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionCommandService.deleteSectionById(sectionId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize - 1); + } + + @Test + @DisplayName("updateSection() : 해당 섹션을 수정할 수 있다.") + void test_updateSection() throws Exception { + //given + final Stations stations = new Stations(new Station("Z"), new Station("V"), 5); + final long sectionId = 3L; + final Section section = new Section(sectionId, stations); + + //when + sectionCommandService.updateSection(section); + + //then + final SectionEntity updatedSection = + sectionDao.findSectionsByLineId(1L) + .stream() + .filter(it -> it.getId().equals(sectionId)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals(updatedSection.getNextStationName(), + section.getStations().getNext().getName()), + () -> assertEquals(updatedSection.getCurrentStationName(), + section.getStations().getCurrent().getName()), + () -> assertEquals(updatedSection.getDistance(), section.getStations().getDistance()), + () -> assertEquals(updatedSection.getId(), section.getId()) + ); + } +} diff --git a/src/test/java/subway/line/application/SectionQueryServiceTest.java b/src/test/java/subway/line/application/SectionQueryServiceTest.java new file mode 100644 index 000000000..3edd3d711 --- /dev/null +++ b/src/test/java/subway/line/application/SectionQueryServiceTest.java @@ -0,0 +1,29 @@ +package subway.line.application; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import helper.IntegrationTestHelper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.line.domain.Section; + +class SectionQueryServiceTest extends IntegrationTestHelper { + + @Autowired + private SectionQueryService sectionQueryService; + + @Test + @DisplayName("searchSectionsByLineId() : 해당 line에 속한 모든 섹션들을 조회할 수 있다.") + void test_searchSectionsByLineId() throws Exception { + //given + final long lineId = 1L; + + //when + final List
sections = sectionQueryService.searchSectionsByLineId(lineId); + + //then + assertEquals(3, sections.size()); + } +} diff --git a/src/test/java/subway/line/application/StationServiceTest.java b/src/test/java/subway/line/application/StationServiceTest.java new file mode 100644 index 000000000..8b9739764 --- /dev/null +++ b/src/test/java/subway/line/application/StationServiceTest.java @@ -0,0 +1,102 @@ +package subway.line.application; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import helper.IntegrationTestHelper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import subway.line.application.dto.StationDeleteRequest; +import subway.line.application.dto.StationRegisterRequest; +import subway.line.dao.SectionDao; +import subway.line.dao.SectionEntity; + +class StationServiceTest extends IntegrationTestHelper { + + @Autowired + private StationService stationService; + + @Autowired + private SectionDao sectionDao; + + @Test + @DisplayName("registerStation() : 역을 저장할 수 있다.") + void test_registerStation() throws Exception { + //given + final String currentStationName = "G"; + final String nextStationName = "K"; + final String lineName = "2호선"; + final int distance = 1; + + final StationRegisterRequest stationRegisterRequest = + new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); + + //when + stationService.registerStation(stationRegisterRequest); + + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(2L) + .stream() + .filter(it -> it.getId().equals(6L)) + .findAny() + .orElseThrow(); + + //then + assertAll( + () -> assertEquals("K", sectionEntity.getCurrentStationName()), + () -> assertEquals("H", sectionEntity.getNextStationName()), + () -> assertEquals(4, sectionEntity.getDistance()) + ); + } + + @Test + @DisplayName("deleteStation() : 해당 역을 삭제할 수 있다.") + void test_deleteStation() throws Exception { + //given + final String lineName = "1호선"; + final String stationName = "B"; + + final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, + stationName); + + //when + stationService.deleteStation(stationDeleteRequest); + + //then + + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(1L) + .stream() + .filter(it -> it.getId().equals(1L)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals("C", sectionEntity.getNextStationName()), + () -> assertEquals(3, sectionEntity.getDistance()) + ); + } + + @Test + @DisplayName("deleteStation() : 라인에 역이 하나만 존재하게 되면 라인이 같이 삭제될 수 있다.") + void test_deleteStation_deleteLine() throws Exception { + //given + final String lineName = "1호선"; + final String stationName1 = "B"; + final String stationName2 = "C"; + + final String stationName3 = "A"; + + stationService.deleteStation(new StationDeleteRequest(lineName, stationName1)); + stationService.deleteStation(new StationDeleteRequest(lineName, stationName2)); + + //when + stationService.deleteStation(new StationDeleteRequest(lineName, stationName3)); + + //then + final int size = sectionDao.findSectionsByLineId(1L).size(); + + assertEquals(0, size); + } +} diff --git a/src/test/java/subway/line/dao/LineDaoTest.java b/src/test/java/subway/line/dao/LineDaoTest.java new file mode 100644 index 000000000..98c0e5f97 --- /dev/null +++ b/src/test/java/subway/line/dao/LineDaoTest.java @@ -0,0 +1,108 @@ +package subway.line.dao; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.Optional; +import org.assertj.core.api.Assertions; +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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class LineDaoTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + private LineDao lineDao; + + @BeforeEach + void setUp() { + lineDao = new LineDao(jdbcTemplate); + } + + @Test + @DisplayName("findByLineName() : 라인 이름으로 라인을 찾을 수 있다.") + void test_findByLineName() throws Exception { + //given + final String lineName = "1호선"; + + //when + final Optional savedLine = lineDao.findByLineName(lineName); + + //then + assertAll( + () -> assertThat(savedLine).isPresent(), + () -> assertEquals(1L, savedLine.get().getId()), + () -> assertEquals(savedLine.get().getName(), lineName) + ); + } + + @Test + @DisplayName("findAll() : 모든 라인을 찾을 수 있다.") + void test_findAll() throws Exception { + //when + final List lineEntities = lineDao.findAll(); + + //then + assertEquals(2, lineEntities.size()); + } + + @Test + @DisplayName("findByLineId() : 라인 id로 라인을 찾을 수 있다.") + void test_findByLineId() throws Exception { + //given + final Long lineId = 2L; + + //when + final Optional savedLine = lineDao.findByLineId(lineId); + + //then + assertAll( + () -> Assertions.assertThat(savedLine).isPresent(), + () -> assertEquals(2L, savedLine.get().getId()), + () -> assertEquals("2호선", savedLine.get().getName()) + ); + } + + @Test + @DisplayName("deleteById() : 라인 id로 라인을 삭제할 수 있다.") + void test_deleteById() throws Exception { + //given + final Long lineId = 2L; + + final int beforeSize = lineDao.findAll().size(); + + //when + lineDao.deleteById(lineId); + + //then + final int afterSize = lineDao.findAll().size(); + assertEquals(afterSize, beforeSize - 1); + } + + @Test + @DisplayName("save() : 라인을 저장할 수 있다.") + void test_save() throws Exception { + //given + final LineEntity lineEntity = new LineEntity("newLine"); + + final int beforeSize = lineDao.findAll().size(); + + //when + lineDao.save(lineEntity); + + //then + final int afterSize = lineDao.findAll().size(); + + assertEquals(afterSize, beforeSize + 1); + } +} diff --git a/src/test/java/subway/line/dao/SectionDaoTest.java b/src/test/java/subway/line/dao/SectionDaoTest.java new file mode 100644 index 000000000..102ce0391 --- /dev/null +++ b/src/test/java/subway/line/dao/SectionDaoTest.java @@ -0,0 +1,136 @@ +package subway.line.dao; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +@JdbcTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class SectionDaoTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + private SectionDao sectionDao; + + @BeforeEach + void setUp() { + sectionDao = new SectionDao(jdbcTemplate); + } + + @Test + @DisplayName("save() : section을 저장할 수 있다.") + void test_save() throws Exception { + //given + final String currentStationName = "H"; + final String nextStationName = "Z"; + final int distance = 1; + final long lineId = 2L; + + final SectionEntity sectionEntity = new SectionEntity( + currentStationName, + nextStationName, + distance, + lineId + ); + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionDao.save(sectionEntity); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize + 1); + } + + @Test + @DisplayName("findSectionsByLineId() : 라인에 속한 모든 section을 조회할 수 있다.") + void test_findSectionsByLineId() throws Exception { + //given + final long lineId = 2L; + + //when + final int size = sectionDao.findSectionsByLineId(lineId).size(); + + //then + assertEquals(4, size); + } + + @Test + @DisplayName("deleteAll() : 라인에 포함되있는 section을 모두 삭제할 수 있다.") + void test_deleteAll() throws Exception { + //given + final long lineId = 2L; + + //when + sectionDao.deleteAll(lineId); + + //then + assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); + } + + @Test + @DisplayName("update() : id를 통해 세션의 정보를 수정할 수 있다.") + void test_update() throws Exception { + //given + final Long sectionId = 7L; + final String updatedCurrentStationName = "Z"; + final String updatedNextStationName = "K"; + final int updatedDistance = 3; + final long lineId = 2L; + + final SectionEntity updatedSectionEntity = new SectionEntity( + 7L, + updatedCurrentStationName, + updatedNextStationName, + updatedDistance, + lineId + ); + + //when + sectionDao.update(updatedSectionEntity); + + //then + final SectionEntity sectionEntity = + sectionDao.findSectionsByLineId(lineId) + .stream() + .filter(it -> it.getId().equals(sectionId)) + .findAny() + .orElseThrow(); + + assertAll( + () -> assertEquals(sectionEntity.getDistance(), updatedSectionEntity.getDistance()), + () -> assertEquals(sectionEntity.getCurrentStationName(), + updatedSectionEntity.getCurrentStationName()), + () -> assertEquals(sectionEntity.getNextStationName(), + updatedSectionEntity.getNextStationName()) + ); + } + + @Test + @DisplayName("deleteById() : id를 통해 section을 삭제할 수 있다.") + void test_deleteById() throws Exception { + //given + final long sectionId = 1L; + final long lineId = 1L; + + final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); + + //when + sectionDao.deleteById(sectionId); + + //then + final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); + + assertEquals(afterSize, beforeSize - 1); + } +} diff --git a/src/test/java/subway/line/domain/LineTest.java b/src/test/java/subway/line/domain/LineTest.java new file mode 100644 index 000000000..9b7f01578 --- /dev/null +++ b/src/test/java/subway/line/domain/LineTest.java @@ -0,0 +1,259 @@ +package subway.line.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LineTest { + + /** + * 기존 : A -> B 추가 : B -> C 결과 : A -> B -> C + */ + @Test + @DisplayName("add() : Line의 맨 끝에 새로운 섹션을 추가할 수 있다.") + void test_add_last() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + + Section 출발_섹션 = new Section(stations1); + final Line line = new Line(1L, "2호선", List.of(출발_섹션)); + + final Section newSection = new Section(stations2); + + //when + line.add(newSection); + + //then + assertAll( + () -> assertEquals(line.getStarter(), 출발_섹션), + () -> assertEquals(line.getStarter().getTo(), newSection) + ); + } + + /** + * 기존 : `A` -> B -> C -> D -> E 추가 : D -> F 결론 : `A` -> B -> C -> D -> F -> E + */ + @Test + @DisplayName("add() : Line의 중간에 새로운 섹션을 추가할 수 있다.") + void test_add_intermediate() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 헤드_섹션 = new Section(stations1); + + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + final Section section4 = new Section(stations4); + + final Line line = new Line(1L, "2호선", List.of(헤드_섹션, section2, section3, section4)); + + final Station current = new Station("D"); + final Station next = new Station("F"); + + final Stations 새로운_stations = new Stations(current, next, 2); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when + line.add(새로운_섹션); + + //then + assertEquals(section3.getTo(), 새로운_섹션); + } + + /** + * 기존 : `A` -> B -> C -> D -> E 추가 : A -> K 결론 : `A` -> K -> B -> C -> D -> E + */ + @Test + @DisplayName("add() : Line의 중간에 새로운 섹션을 추가할 수 있다.") + void test_add_intermediate2() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 헤드_섹션 = new Section(stations1); + + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + final Section section4 = new Section(stations4); + + final Line line = new Line(1L, "2호선", List.of(헤드_섹션, section2, section3, section4)); + + final Station current = new Station("A"); + final Station next = new Station("K"); + + final Stations 새로운_stations = new Stations(current, next, 2); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when + line.add(새로운_섹션); + + //then + assertAll( + () -> assertEquals(헤드_섹션.getTo(), section2), + () -> assertEquals(새로운_섹션.getTo(), 헤드_섹션), + () -> assertEquals(3, 헤드_섹션.getStations().getDistance()) + ); + } + + /** + * 기존 : A -> B -> C 추가 : Z -> A 결론 : Z -> A -> B -> C + */ + @Test + @DisplayName("add() : 새롭게 추가된 섹션이 Line의 새로운 Starter가 될 수 있다.") + void test_add_newStarter() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("Z"), new Station("A"), 4); + + Section 스타터_바뀔_예정_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + + final Line line = new Line(1L, "2호선", List.of(스타터_바뀔_예정_섹션, section2)); + + final Section 새로운_섹션 = new Section(stations3); + + //when + line.add(새로운_섹션); + + //then + assertAll( + () -> assertEquals(line.getStarter(), 새로운_섹션), + () -> assertEquals(새로운_섹션.getTo(), 스타터_바뀔_예정_섹션) + ); + } + + @Test + @DisplayName("add() : Line에 새롭게 추가되지 못하는 섹션을 넣을 경우 IllegalArgumentException이 발생할 수 있다.") + void test_add_IllegalArgumentException() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("B"), new Station("A"), 4); + + Section 스타터_바뀔_예정_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + + final Line line = new Line(1L, "2호선", List.of(스타터_바뀔_예정_섹션, section2)); + + final Section 새로운_섹션 = new Section(stations3); + + //when & then + assertThatThrownBy(() -> line.add(새로운_섹션)) + .isInstanceOf(IllegalArgumentException.class); + } + + + /** + * 기존 : A -> B -> C -> D 삭제 : B 결론 : A -> C -> D + */ + @Test + @DisplayName("delete() : Line 중간에 있는 Section을 삭제할 수 있다.") + void test_delete() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section starter = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); + + //when + line.delete(new Station("B")); + + //then + assertAll( + () -> assertEquals(starter.getTo(), section3), + () -> assertNull(section2.getTo()), + () -> assertEquals(9, starter.getStations().getDistance()), + () -> assertTrue(starter.getStations().getNext() + .isSame(section2.getStations().getNext())) + ); + } + + /** + * 기존 : A -> B -> C -> D 삭제 : A 결론 : B -> C -> D + */ + @Test + @DisplayName("delete() : Line의 starter를 삭제할 수 있다.") + void test_delete_starter() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section starter = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); + + //when + line.delete(new Station("A")); + + //then + assertAll( + () -> assertEquals(section2.getTo(), section3), + () -> assertEquals(line.getStarter(), section2), + () -> assertNull(starter.getTo()) + ); + } + + /** + * 기존 : A -> B -> C -> D 삭제 : D 결과 : A -> B -> C + */ + @Test + @DisplayName("delete() : Line의 마지막 역을 삭제할 수 있다.") + void test_delete_last_station() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section starter = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line = new Line(1L, "2호선", List.of(starter, section2, section3)); + + //when + line.delete(new Station("D")); + + //then + assertNull(section2.getTo()); + } + + /** + * 기존 : A -> B 삭제 : B 결과 : Line 삭제 + */ + @Test + @DisplayName("delete() : Line 에 Section 이 하나밖에 없을 때, 역을 삭제할 경우 Line이 사라진다.") + void test_delete_line() throws Exception { + //given + final Stations stations = new Stations(new Station("A"), new Station("B"), 5); + final Line line = new Line(1L, "2호선", List.of(new Section(stations))); + + //when + line.delete(new Station("B")); + + //then + assertNull(line.getStarter()); + } +} diff --git a/src/test/java/subway/line/domain/SectionTest.java b/src/test/java/subway/line/domain/SectionTest.java new file mode 100644 index 000000000..5864d085c --- /dev/null +++ b/src/test/java/subway/line/domain/SectionTest.java @@ -0,0 +1,179 @@ +package subway.line.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class SectionTest { + + /** + * 기존 : A-B-C-D-E 추가 : D-F 결과 : IllegalArgumentException + */ + @Test + @DisplayName("addNext() : 중간에 끼어드는 섹션의 길이가 현재 연결된 섹션의 길이보다 크면 IllegalArgumentException가 발생한다.") + void test_addNext_IllegalArgumentException() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 시작_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + 시작_섹션.addNext(section2); + + final Section section3 = new Section(stations3); + 시작_섹션.addNext(section3); + + final Section section4 = new Section(stations4); + 시작_섹션.addNext(section4); + + final Station current = new Station("D"); + final Station next = new Station("F"); + + final Stations 새로운_stations = new Stations(current, next, 5); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when & then + assertThatThrownBy(() -> 시작_섹션.addNext(새로운_섹션)) + .isInstanceOf(IllegalArgumentException.class); + } + + /** + * 기존 : A-B-C-D-E 추가 : D-F 결과 : A-B-C-D-F-E + */ + @Test + @DisplayName("addNext() : 중간에 끼어드는 섹션의 길이가 현재 연결된 섹션의 길이보다 작으면 섹션을 추가할 수 있다.") + void test_addNext() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 시작_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + 시작_섹션.addNext(section2); + + final Section section3 = new Section(stations3); + 시작_섹션.addNext(section3); + + final Section section4 = new Section(stations4); + 시작_섹션.addNext(section4); + + final Station current = new Station("D"); + final Station next = new Station("F"); + + final Stations 새로운_stations = new Stations(current, next, 2); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when + 시작_섹션.addNext(새로운_섹션); + + //then + assertAll( + () -> assertEquals(section3.getTo(), 새로운_섹션), + () -> assertEquals(새로운_섹션.getTo(), section4), + () -> assertEquals(1, 새로운_섹션.getTo().getStations().getDistance() + ) + ); + } + + /** + * 기존 : A-B-C-D-E 추가 : E-F 결과 : A-B-C-D-E-F + */ + @Test + @DisplayName("addNext() : 새로운 섹션을 맨 마지막에 추가할 수 있다.") + void test_addNext_last() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 시작_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + 시작_섹션.addNext(section2); + + final Section section3 = new Section(stations3); + 시작_섹션.addNext(section3); + + final Section section4 = new Section(stations4); + 시작_섹션.addNext(section4); + + final Station current = new Station("E"); + final Station next = new Station("F"); + + final Stations 새로운_stations = new Stations(current, next, 2); + + final Section 새로운_섹션 = new Section(새로운_stations); + + //when + 시작_섹션.addNext(새로운_섹션); + + //then + assertAll( + () -> assertEquals(section4.getTo(), 새로운_섹션) + ); + } + + /** + * 기존 : A -> B 추가 : B -> C 결과 : A -> B -> C + */ + @Test + @DisplayName("isLinked() : 시작 섹션의 목적지와 도착 섹션의 출발지가 같으면 두 섹션은 연결될 수 있다.") + void test_isLinked() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + + final Section start = new Section(stations1); + final Section end = new Section(stations2); + + //when & then + assertTrue(end.isLinked(start)); + } + + /** + * 기존 : A-B-C-D-E 삭제 : C 결과 : A-B-D-E + */ + @Test + @DisplayName("delete() : 중간 섹션을 삭제할 수 있다.") + void test_delete() throws Exception { + //given + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 5); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 4); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + final Stations stations4 = new Stations(new Station("D"), new Station("E"), 3); + + Section 시작_섹션 = new Section(stations1); + final Section section2 = new Section(stations2); + 시작_섹션.addNext(section2); + + final Section section3 = new Section(stations3); + 시작_섹션.addNext(section3); + + final Section section4 = new Section(stations4); + 시작_섹션.addNext(section4); + + final Station 삭제할_역 = new Station("C"); + + //when + 시작_섹션.delete(삭제할_역); + + //then + assertAll( + () -> assertEquals(section2.getTo(), section4), + () -> assertNull(section3.getTo()), + () -> assertTrue(section2.getStations().getNext().isSame(section3.getStations().getNext())), + () -> assertEquals(7, section2.getStations().getDistance()) + ); + } +} diff --git a/src/test/java/subway/line/domain/StationTest.java b/src/test/java/subway/line/domain/StationTest.java new file mode 100644 index 000000000..645c98910 --- /dev/null +++ b/src/test/java/subway/line/domain/StationTest.java @@ -0,0 +1,20 @@ +package subway.line.domain; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class StationTest { + + @Test + @DisplayName("isSame() : 이름이 같으면 같은 역이다.") + void test_isSame() throws Exception { + //given + final Station station1 = new Station("A"); + final Station station2 = new Station("A"); + + //when & then + assertTrue(station1.isSame(station2)); + } +} diff --git a/src/test/java/subway/line/domain/StationsTest.java b/src/test/java/subway/line/domain/StationsTest.java new file mode 100644 index 000000000..471d83362 --- /dev/null +++ b/src/test/java/subway/line/domain/StationsTest.java @@ -0,0 +1,29 @@ +package subway.line.domain; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class StationsTest { + + @Test + @DisplayName("isLinked() : 두 역이 이어져있는지 확인할 수 있다.") + void test_isLinked() throws Exception { + //given + final Stations stations1 = new Stations( + new Station("A"), + new Station("B"), + 3 + ); + + final Stations stations2 = new Stations( + new Station("B"), + new Station("C"), + 4 + ); + + //when & then + assertTrue(stations1.isLinked(stations2)); + } +} diff --git a/src/test/java/subway/line/presentation/LineControllerTest.java b/src/test/java/subway/line/presentation/LineControllerTest.java new file mode 100644 index 000000000..af697af15 --- /dev/null +++ b/src/test/java/subway/line/presentation/LineControllerTest.java @@ -0,0 +1,141 @@ +package subway.line.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import subway.line.application.LineCommandService; +import subway.line.application.LineQueryService; +import subway.line.application.dto.RegisterLineRequest; +import subway.line.domain.Line; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; + +@WebMvcTest(LineController.class) +class LineControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private LineCommandService lineCommandService; + + @MockBean + private LineQueryService lineQueryService; + + @Test + @DisplayName("showLines() : lineName이 주어지면 해당 line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLines() throws Exception { + //given + final String lineName = "2호선"; + + final List lines = createDefaultLines(); + + when(lineQueryService.searchLines(any())) + .thenReturn(lines); + + //when & then + mockMvc.perform(get("/lines?lineName={lineName}", lineName)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("showLines() : lineName이 주어지지 않으면 모든 line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLines_all() throws Exception { + //given + final List lines = createDefaultLines(); + + when(lineQueryService.searchLines(any())) + .thenReturn(lines); + + //when & then + mockMvc.perform(get("/lines")) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("showLine() : id를 통해 해당 Line을 성공적으로 조회할 때 200 OK을 반환한다.") + void test_showLine() throws Exception { + //given + final List lines = createDefaultLines(); + final long lineId = 1L; + + when(lineQueryService.searchByLineId(anyLong())) + .thenReturn(lines.get(0)); + + //when & then + mockMvc.perform(get("/lines/{line-id}", lineId)) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("registerLine() : Line을 성공적으로 저장할 때 201 Created를 반환한다.") + void test_registerLine() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "B"; + final String lineName = "line"; + final int distance = 4; + + final RegisterLineRequest registerLineRequest = + new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); + + final String bodyData = objectMapper.writeValueAsString(registerLineRequest); + + doNothing().when(lineCommandService) + .registerLine(any()); + + when(lineQueryService.searchByLineName(any())) + .thenReturn(createDefaultLines().get(0)); + + //when & then + mockMvc.perform(post("/lines") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isCreated()); + } + + private List createDefaultLines() { + final Stations stations1 = new Stations(new Station("A"), new Station("B"), 1); + final Stations stations2 = new Stations(new Station("B"), new Station("C"), 2); + final Stations stations3 = new Stations(new Station("C"), new Station("D"), 3); + + final Section section1 = new Section(stations1); + final Section section2 = new Section(stations2); + final Section section3 = new Section(stations3); + + final Line line1 = new Line(1L, "1호선", List.of(section1, section2, section3)); + + final Stations stations4 = new Stations(new Station("B"), new Station("F"), 4); + final Stations stations5 = new Stations(new Station("F"), new Station("G"), 11); + final Stations stations6 = new Stations(new Station("G"), new Station("H"), 5); + final Stations stations7 = new Stations(new Station("H"), new Station("D"), 4); + + final Section section4 = new Section(stations4); + final Section section5 = new Section(stations5); + final Section section6 = new Section(stations6); + final Section section7 = new Section(stations7); + + final Line line2 = new Line(2L, "2호선", + List.of(section4, section5, section6, section7)); + + return List.of(line1, line2); + } +} diff --git a/src/test/java/subway/line/presentation/StationControllerTest.java b/src/test/java/subway/line/presentation/StationControllerTest.java new file mode 100644 index 000000000..78ffea339 --- /dev/null +++ b/src/test/java/subway/line/presentation/StationControllerTest.java @@ -0,0 +1,78 @@ +package subway.line.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import subway.line.application.StationService; +import subway.line.application.dto.StationDeleteRequest; +import subway.line.application.dto.StationRegisterRequest; + +@WebMvcTest(StationController.class) +class StationControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private StationService stationService; + + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("registerStation() : station이 정상적으로 저장되면 201 Created를 반환한다.") + void test_registerStation() throws Exception { + //given + final String currentStationName = "A"; + final String nextStationName = "B"; + final String lineName = "line"; + final int distance = 4; + + final StationRegisterRequest stationRegisterRequest = + new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); + + final String bodyData = objectMapper.writeValueAsString(stationRegisterRequest); + + doNothing().when(stationService) + .registerStation(any()); + + //when & then + mockMvc.perform(post("/stations") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isCreated()); + } + + @Test + @DisplayName("deleteStation() : station 이 정상적으로 삭제되면 204 No Content 를 반환한다.") + void test_deleteStation() throws Exception { + //given + final String lineName = "line"; + final String stationName = "station"; + + final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, + stationName); + + final String bodyData = objectMapper.writeValueAsString(stationDeleteRequest); + + doNothing().when(stationService) + .deleteStation(any()); + + //when & then + mockMvc.perform(delete("/stations") + .contentType(MediaType.APPLICATION_JSON) + .content(bodyData)) + .andExpect(status().isNoContent()); + } +} diff --git a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java b/src/test/java/subway/policy/application/ChargePolicyCompositeTest.java similarity index 75% rename from src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java rename to src/test/java/subway/policy/application/ChargePolicyCompositeTest.java index 99fb1c00e..78f7ceffe 100644 --- a/src/test/java/subway/domain/policy/ChargePolicyCompositeTest.java +++ b/src/test/java/subway/policy/application/ChargePolicyCompositeTest.java @@ -1,4 +1,4 @@ -package subway.domain.policy; +package subway.policy.application; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -8,14 +8,14 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.policy.discount.AgeDiscountPolicy; -import subway.domain.policy.discount.DiscountCondition; -import subway.domain.policy.fare.DistanceFarePolicy; -import subway.domain.policy.fare.LineFarePolicy; -import subway.domain.station.Station; -import subway.service.LineQueryService; +import subway.line.application.LineQueryService; +import subway.line.domain.Line; +import subway.line.domain.Station; +import subway.policy.infrastructure.AgeDiscountPolicy; +import subway.policy.infrastructure.DiscountCondition; +import subway.policy.infrastructure.DistanceFarePolicy; +import subway.policy.infrastructure.LineFarePolicy; +import subway.value_object.Money; @SpringBootTest class ChargePolicyCompositeTest { @@ -36,13 +36,7 @@ void setUp() { } /** - * - * 11 5 - * F - G - H - * 4 | | 2 - * | | - * A - B - C - D - * 1 2 3 + * 11 5 F - G - H 4 | | 2 | | A - B - C - D 1 2 3 */ @Test @DisplayName("calculate() : 모든 추가 요금 정책을 계산할 수 있다.") diff --git a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java b/src/test/java/subway/policy/infrastructure/DistanceFarePolicyTest.java similarity index 91% rename from src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java rename to src/test/java/subway/policy/infrastructure/DistanceFarePolicyTest.java index 38ee6a502..fac2cf10d 100644 --- a/src/test/java/subway/domain/policy/fare/DistanceFarePolicyTest.java +++ b/src/test/java/subway/policy/infrastructure/DistanceFarePolicyTest.java @@ -1,4 +1,4 @@ -package subway.domain.policy.fare; +package subway.policy.infrastructure; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -13,13 +13,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.MockedStatic; -import subway.domain.Distance; -import subway.domain.Money; -import subway.domain.line.Line; -import subway.domain.route.JgraphtRouteFinder; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; +import subway.line.domain.Line; +import subway.line.domain.Section; +import subway.line.domain.Station; +import subway.line.domain.Stations; +import subway.policy.domain.SubwayFarePolicy; +import subway.route.application.JgraphtRouteFinder; +import subway.value_object.Distance; +import subway.value_object.Money; class DistanceFarePolicyTest { diff --git a/src/test/java/subway/service/RouteQueryServiceTest.java b/src/test/java/subway/route/application/RouteQueryServiceTest.java similarity index 89% rename from src/test/java/subway/service/RouteQueryServiceTest.java rename to src/test/java/subway/route/application/RouteQueryServiceTest.java index 0284f36c3..a76456e6f 100644 --- a/src/test/java/subway/service/RouteQueryServiceTest.java +++ b/src/test/java/subway/route/application/RouteQueryServiceTest.java @@ -1,4 +1,4 @@ -package subway.service; +package subway.route.application; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -9,8 +9,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import subway.service.dto.ShortestRouteRequest; -import subway.service.dto.ShortestRouteResponse; +import subway.route.application.dto.ShortestRouteRequest; +import subway.route.application.dto.ShortestRouteResponse; class RouteQueryServiceTest extends IntegrationTestHelper { diff --git a/src/test/java/subway/controller/RouteControllerTest.java b/src/test/java/subway/route/presentation/RouteControllerTest.java similarity index 94% rename from src/test/java/subway/controller/RouteControllerTest.java rename to src/test/java/subway/route/presentation/RouteControllerTest.java index bc9ee30fa..e123fe32f 100644 --- a/src/test/java/subway/controller/RouteControllerTest.java +++ b/src/test/java/subway/route/presentation/RouteControllerTest.java @@ -1,4 +1,4 @@ -package subway.controller; +package subway.route.presentation; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -12,8 +12,8 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; -import subway.service.RouteQueryService; -import subway.service.dto.ShortestRouteResponse; +import subway.route.application.RouteQueryService; +import subway.route.application.dto.ShortestRouteResponse; @WebMvcTest(RouteController.class) class RouteControllerTest { diff --git a/src/test/java/subway/service/LineCommandServiceTest.java b/src/test/java/subway/service/LineCommandServiceTest.java deleted file mode 100644 index f02734620..000000000 --- a/src/test/java/subway/service/LineCommandServiceTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package subway.service; - -import helper.IntegrationTestHelper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import subway.dao.LineDao; -import subway.dao.LineEntity; -import subway.exception.line.CanNotDuplicatedLineNameException; -import subway.service.dto.RegisterLineRequest; - -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertEquals; - -class LineCommandServiceTest extends IntegrationTestHelper { - - @Autowired - private LineCommandService lineCommandService; - - @Autowired - private LineDao lineDao; - - @Test - @DisplayName("deleteLine() : line id 가 주어졌을 때 해당 라인을 삭제할 수 있다.") - void test_deleteLine() throws Exception { - //given - final long lineId = 1L; - - //when - lineCommandService.deleteLine(lineId); - - //then - final Optional savedLine = lineDao.findByLineId(lineId); - - assertThat(savedLine).isEmpty(); - } - - @Test - @DisplayName("registerLine() : 새로운 line을 생성할 수 있다.") - void test_registerLine() throws Exception { - //given - final String currentStationName = "D"; - final String nextStationName = "Z"; - final String lineName = "line"; - final int distance = 4; - - final RegisterLineRequest registerLineRequest = - new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); - - final int beforeSize = lineDao.findAll().size(); - - //when - lineCommandService.registerLine(registerLineRequest); - - //then - final int afterSize = lineDao.findAll().size(); - assertEquals(afterSize, beforeSize + 1); - } - - @Test - @DisplayName("registerLine() : line을 새로 생성할 때, 기존에 있는 lineName이 존재한다면 CanNotDuplicatedLineNameException이 발생한다.") - void test_registerLine_CanNotDuplicatedLineNameException() throws Exception { - //given - final String currentStationName = "D"; - final String nextStationName = "Z"; - final String lineName = "1호선"; - final int distance = 4; - - final RegisterLineRequest registerLineRequest = - new RegisterLineRequest(currentStationName, nextStationName, lineName, distance); - - //when & then - assertThatThrownBy(() -> lineCommandService.registerLine(registerLineRequest)) - .isInstanceOf(CanNotDuplicatedLineNameException.class); - } -} diff --git a/src/test/java/subway/service/LineQueryServiceTest.java b/src/test/java/subway/service/LineQueryServiceTest.java deleted file mode 100644 index 031bc47fc..000000000 --- a/src/test/java/subway/service/LineQueryServiceTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package subway.service; - -import helper.IntegrationTestHelper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.springframework.beans.factory.annotation.Autowired; -import subway.domain.line.Line; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - -class LineQueryServiceTest extends IntegrationTestHelper { - - @Autowired - private LineQueryService lineQueryService; - - @Test - @DisplayName("searchLines() : lineName이 존재하지 않으면 모든 line을 조회할 수 있다.") - void test_searchLines_all() throws Exception { - //given - final String lineName = null; - - //when - final List lines = lineQueryService.searchLines(lineName); - - //then - assertEquals(2, lines.size()); - } - - @Test - @DisplayName("searchLines() : lineName을 통해 해당 line을 조회할 수 있다.") - void test_searchLines() throws Exception { - //given - final String lineName = "1호선"; - - //when - final List lines = lineQueryService.searchLines(lineName); - - //then - assertAll( - () -> assertEquals(1, lines.size()), - () -> assertEquals(lines.get(0).getName(), lineName) - ); - } - - @Test - @DisplayName("searchAllLine() : 모든 Line을 조회할 수 있다.") - void test_searchAllLine() throws Exception { - //when - final List lines = lineQueryService.searchAllLine(); - - //then - assertEquals(2, lines.size()); - } - - @Test - @DisplayName("searchByLineName() : lineName을 통해 해당 line을 조회할 수 있다.") - void test_searchByLineName() throws Exception { - //given - final String lineName = "1호선"; - - //when - final Line line = lineQueryService.searchByLineName(lineName); - - //then - assertEquals(line.getName(), lineName); - } - - @Test - @DisplayName("searchByLineId() : line id를 통해 해당 line을 조회할 수 있다.") - void test_searchByLineId() throws Exception { - //given - final Long lineId = 1L; - - //when - final Line line = lineQueryService.searchByLineId(lineId); - - //then - assertEquals(line.getId(), lineId); - } - - @ParameterizedTest - @CsvSource({ - "1호선, true", - "2호선, true", - "3호선, false" - }) - @DisplayName("isExistLine() : lineName을 통해 해당 line이 존재하는지 알 수 있다.") - void test_isExistLine(final String lineName, final boolean isExist) throws Exception { - //then - assertEquals(isExist, lineQueryService.isExistLine(lineName)); - } -} diff --git a/src/test/java/subway/service/SectionCommandServiceTest.java b/src/test/java/subway/service/SectionCommandServiceTest.java deleted file mode 100644 index 024705e9e..000000000 --- a/src/test/java/subway/service/SectionCommandServiceTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package subway.service; - -import helper.IntegrationTestHelper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import subway.dao.SectionDao; -import subway.dao.SectionEntity; -import subway.domain.section.Section; -import subway.domain.station.Station; -import subway.domain.station.Stations; -import subway.exception.section.CanNotDuplicatedSectionException; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - -class SectionCommandServiceTest extends IntegrationTestHelper { - - @Autowired - private SectionCommandService sectionCommandService; - - @Autowired - private SectionDao sectionDao; - - @Test - @DisplayName("registerSection() : 섹션을 저장할 수 있다.") - void test_registerSection() throws Exception { - //given - final String currentStationName = "D"; - final String nextStationName = "Z"; - final Long lineId = 2L; - final int distance = 4; - - final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); - - //when - sectionCommandService.registerSection(currentStationName, nextStationName, distance, lineId); - - //then - final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); - - assertEquals(afterSize, beforeSize + 1); - } - - @Test - @DisplayName("registerSection() : 섹션을 저장할 때, 해당 호선에 같은 섹션이 있으면 CanNotDuplicatedSectionException이 발생한다.") - void test_registerSection_CanNotDuplicatedSectionException() throws Exception { - //given - final String currentStationName = "B"; - final String nextStationName = "F"; - final Long lineId = 2L; - final int distance = 4; - - //when & then - assertThatThrownBy( - () -> sectionCommandService.registerSection(currentStationName, nextStationName, distance, lineId)) - .isInstanceOf(CanNotDuplicatedSectionException.class); - } - - @Test - @DisplayName("deleteAll() : 주어진 호선에 있는 섹션들을 모두 삭제할 수 있다.") - void test_deleteAll() throws Exception { - //given - final long lineId = 1L; - - //when - sectionCommandService.deleteAll(lineId); - - //then - assertEquals(0, sectionDao.findSectionsByLineId(lineId).size()); - } - - @Test - @DisplayName("deleteSection() : section id를 통해 섹션을 삭제할 수 있다.") - void test_deleteSection() throws Exception { - //given - final long sectionId = 1L; - final long lineId = 1L; - - final int beforeSize = sectionDao.findSectionsByLineId(lineId).size(); - - //when - sectionCommandService.deleteSectionById(sectionId); - - //then - final int afterSize = sectionDao.findSectionsByLineId(lineId).size(); - - assertEquals(afterSize, beforeSize - 1); - } - - @Test - @DisplayName("updateSection() : 해당 섹션을 수정할 수 있다.") - void test_updateSection() throws Exception { - //given - final Stations stations = new Stations(new Station("Z"), new Station("V"), 5); - final long sectionId = 3L; - final Section section = new Section(sectionId, stations); - - //when - sectionCommandService.updateSection(section); - - //then - final SectionEntity updatedSection = - sectionDao.findSectionsByLineId(1L) - .stream() - .filter(it -> it.getId().equals(sectionId)) - .findAny() - .orElseThrow(); - - assertAll( - () -> assertEquals(updatedSection.getNextStationName(), section.getStations().getNext().getName()), - () -> assertEquals(updatedSection.getCurrentStationName(), - section.getStations().getCurrent().getName()), - () -> assertEquals(updatedSection.getDistance(), section.getStations().getDistance()), - () -> assertEquals(updatedSection.getId(), section.getId()) - ); - } -} diff --git a/src/test/java/subway/service/SectionQueryServiceTest.java b/src/test/java/subway/service/SectionQueryServiceTest.java deleted file mode 100644 index 48eac7e8e..000000000 --- a/src/test/java/subway/service/SectionQueryServiceTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package subway.service; - -import helper.IntegrationTestHelper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import subway.domain.section.Section; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class SectionQueryServiceTest extends IntegrationTestHelper { - - @Autowired - private SectionQueryService sectionQueryService; - - @Test - @DisplayName("searchSectionsByLineId() : 해당 line에 속한 모든 섹션들을 조회할 수 있다.") - void test_searchSectionsByLineId() throws Exception { - //given - final long lineId = 1L; - - //when - final List
sections = sectionQueryService.searchSectionsByLineId(lineId); - - //then - assertEquals(3, sections.size()); - } -} diff --git a/src/test/java/subway/service/StationServiceTest.java b/src/test/java/subway/service/StationServiceTest.java deleted file mode 100644 index d544af6df..000000000 --- a/src/test/java/subway/service/StationServiceTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package subway.service; - -import helper.IntegrationTestHelper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import subway.dao.SectionDao; -import subway.dao.SectionEntity; -import subway.service.dto.StationDeleteRequest; -import subway.service.dto.StationRegisterRequest; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; - -class StationServiceTest extends IntegrationTestHelper { - - @Autowired - private StationService stationService; - - @Autowired - private SectionDao sectionDao; - - @Test - @DisplayName("registerStation() : 역을 저장할 수 있다.") - void test_registerStation() throws Exception { - //given - final String currentStationName = "G"; - final String nextStationName = "K"; - final String lineName = "2호선"; - final int distance = 1; - - final StationRegisterRequest stationRegisterRequest = - new StationRegisterRequest(lineName, currentStationName, nextStationName, distance); - - //when - stationService.registerStation(stationRegisterRequest); - - final SectionEntity sectionEntity = - sectionDao.findSectionsByLineId(2L) - .stream() - .filter(it -> it.getId().equals(6L)) - .findAny() - .orElseThrow(); - - //then - assertAll( - () -> assertEquals("K", sectionEntity.getCurrentStationName()), - () -> assertEquals("H", sectionEntity.getNextStationName()), - () -> assertEquals(4, sectionEntity.getDistance()) - ); - } - - @Test - @DisplayName("deleteStation() : 해당 역을 삭제할 수 있다.") - void test_deleteStation() throws Exception { - //given - final String lineName = "1호선"; - final String stationName = "B"; - - final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName); - - //when - stationService.deleteStation(stationDeleteRequest); - - //then - - final SectionEntity sectionEntity = - sectionDao.findSectionsByLineId(1L) - .stream() - .filter(it -> it.getId().equals(1L)) - .findAny() - .orElseThrow(); - - assertAll( - () -> assertEquals("C", sectionEntity.getNextStationName()), - () -> assertEquals(3, sectionEntity.getDistance()) - ); - } - - @Test - @DisplayName("deleteStation() : 라인에 역이 하나만 존재하게 되면 라인이 같이 삭제될 수 있다.") - void test_deleteStation_deleteLine() throws Exception { - //given - final String lineName = "1호선"; - final String stationName1 = "B"; - final String stationName2 = "C"; - - final String stationName3 = "A"; - - final StationDeleteRequest stationDeleteRequest = new StationDeleteRequest(lineName, stationName1); - stationService.deleteStation(new StationDeleteRequest(lineName, stationName1)); - stationService.deleteStation(new StationDeleteRequest(lineName, stationName2)); - - //when - stationService.deleteStation(new StationDeleteRequest(lineName, stationName3)); - - //then - final int size = sectionDao.findSectionsByLineId(1L).size(); - - assertEquals(0, size); - } -} diff --git a/src/test/java/subway/value_object/MoneyTest.java b/src/test/java/subway/value_object/MoneyTest.java new file mode 100644 index 000000000..cb201bc77 --- /dev/null +++ b/src/test/java/subway/value_object/MoneyTest.java @@ -0,0 +1,48 @@ +package subway.value_object; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class MoneyTest { + + @ParameterizedTest + @CsvSource({ + "10000, 35, 6500", + "1000, 10, 900", + "3500, 10, 3150" + }) + @DisplayName("discountPercent() : 할인을 받고 난 금액을 계산할 수 있다.") + void test_discountPercent(final int origin, final int percent, final int result) + throws Exception { + //given + final Money originMoney = new Money(origin); + final Money resultMoney = new Money(result); + + //when & then + assertEquals(resultMoney, originMoney.calculateDiscountedPrice(percent)); + } + + @Test + @DisplayName("constructor() : 돈이 음수가 되면 IllegalArgumentException가 발생합니다.") + void test_constructor_IllegalArgumentException() throws Exception { + //when & then + assertThatThrownBy(() -> new Money(-1)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("discountPercent() : 할인율이 0퍼센트이면 그대로 값을 반환합니다.") + void test_discountPercent_zeroPercent() throws Exception { + //given + final Money money = new Money(10000); + final int percentage = 0; + + //when & then + assertEquals(money, money.calculateDiscountedPrice(percentage)); + } +} diff --git a/src/test/java/subway/yml/ProfileActiveFirstTest.java b/src/test/java/subway/yml/ProfileActiveFirstTest.java index e4f429a22..f5fe5f5ed 100644 --- a/src/test/java/subway/yml/ProfileActiveFirstTest.java +++ b/src/test/java/subway/yml/ProfileActiveFirstTest.java @@ -1,31 +1,30 @@ package subway.yml; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; - -import javax.sql.DataSource; -import subway.domain.route.JgraphtRouteFinder; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import subway.route.application.JgraphtRouteFinder; @SpringBootTest @ActiveProfiles({"test", "first"}) -public class ProfileActiveFirstTest { +class ProfileActiveFirstTest { - @Autowired - private DataSource dataSource; + @Autowired + private DataSource dataSource; - @MockBean - private JgraphtRouteFinder jgraphtRouteFinder; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; - @Test - void test_first() throws Exception { - String expectedDatabaseUrl = "jdbc:h2:mem:first"; - String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + @Test + void test_first() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:first"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); - assertEquals(expectedDatabaseUrl, actualDatabaseUrl); - } + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } } diff --git a/src/test/java/subway/yml/ProfileActiveSecondTest.java b/src/test/java/subway/yml/ProfileActiveSecondTest.java index 326437e5d..2c866e30b 100644 --- a/src/test/java/subway/yml/ProfileActiveSecondTest.java +++ b/src/test/java/subway/yml/ProfileActiveSecondTest.java @@ -1,31 +1,30 @@ package subway.yml; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; - -import javax.sql.DataSource; -import subway.domain.route.JgraphtRouteFinder; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import subway.route.application.JgraphtRouteFinder; @SpringBootTest @ActiveProfiles({"second", "test"}) -public class ProfileActiveSecondTest { +class ProfileActiveSecondTest { - @Autowired - private DataSource dataSource; + @Autowired + private DataSource dataSource; - @MockBean - private JgraphtRouteFinder jgraphtRouteFinder; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; - @Test - void test_default1() throws Exception { - String expectedDatabaseUrl = "jdbc:h2:mem:second"; - String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + @Test + void test_default1() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:second"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); - assertEquals(expectedDatabaseUrl, actualDatabaseUrl); - } + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } } diff --git a/src/test/java/subway/yml/ProfileActiveThirdTest.java b/src/test/java/subway/yml/ProfileActiveThirdTest.java index 3b2883cd8..75079ac37 100644 --- a/src/test/java/subway/yml/ProfileActiveThirdTest.java +++ b/src/test/java/subway/yml/ProfileActiveThirdTest.java @@ -1,31 +1,30 @@ package subway.yml; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; - -import javax.sql.DataSource; -import subway.domain.route.JgraphtRouteFinder; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import subway.route.application.JgraphtRouteFinder; @SpringBootTest @ActiveProfiles({"third", "test"}) -public class ProfileActiveThirdTest { +class ProfileActiveThirdTest { - @Autowired - private DataSource dataSource; + @Autowired + private DataSource dataSource; - @MockBean - private JgraphtRouteFinder jgraphtRouteFinder; + @MockBean + private JgraphtRouteFinder jgraphtRouteFinder; - @Test - void test_third() throws Exception { - String expectedDatabaseUrl = "jdbc:h2:mem:third"; - String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); + @Test + void test_third() throws Exception { + String expectedDatabaseUrl = "jdbc:h2:mem:third"; + String actualDatabaseUrl = dataSource.getConnection().getMetaData().getURL(); - assertEquals(expectedDatabaseUrl, actualDatabaseUrl); - } + assertEquals(expectedDatabaseUrl, actualDatabaseUrl); + } }