diff --git a/README.md b/README.md index e0d497e77f..3d7c6d7404 100644 --- a/README.md +++ b/README.md @@ -37,3 +37,19 @@ ## ๐Ÿ“ License This project is [MIT](https://github.com/woowacourse/atdd-subway-map/blob/master/LICENSE) licensed. + + +## ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ชฉ๋ก + +- ์ง€ํ•˜์ฒ  ์—ญ +- [x] ์ง€ํ•˜์ฒ ์—ญ ์ƒ์„ฑ ์‹œ ์ด๋ฏธ ๋“ฑ๋ก๋œ ์ด๋ฆ„์œผ๋กœ ์š”์ฒญํ•œ๋‹ค๋ฉด ์—๋Ÿฌ๋ฅผ ์‘๋‹ต + +- ์ง€ํ•˜์ฒ  ๋…ธ์„  +- [x] ๋™์ผํ•œ ๋…ธ์„  ์ƒ์„ฑ ๋ถˆ๊ฐ€ +- api +- [x] post - /lines ๋“ฑ๋ก - name, color +- [x] get - /lines - List - id, name, color +- [ ] get - /lines/{id} - id, name, color +- [ ] put - /lines/{id} - name, color +- [ ] delete - /lines/{id} + diff --git a/src/main/java/wooteco/subway/SubwayApplication.java b/src/main/java/wooteco/subway/SubwayApplication.java index bb8759d7c9..eab1d1b0cc 100644 --- a/src/main/java/wooteco/subway/SubwayApplication.java +++ b/src/main/java/wooteco/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/wooteco/subway/dao/LineRepository.java b/src/main/java/wooteco/subway/dao/LineRepository.java new file mode 100644 index 0000000000..4a12e5eaa4 --- /dev/null +++ b/src/main/java/wooteco/subway/dao/LineRepository.java @@ -0,0 +1,23 @@ +package wooteco.subway.dao; + +import wooteco.subway.domain.Line; + +import java.util.List; +import java.util.Optional; + +public interface LineRepository { + + Line save(Line line); + + List findAll(); + + Optional findById(Long id); + + Optional findByName(String name); + + void update(Long id, Line line); + + void deleteById(Long id); + + boolean existByName(String name); +} diff --git a/src/main/java/wooteco/subway/dao/LineRepositoryImpl.java b/src/main/java/wooteco/subway/dao/LineRepositoryImpl.java new file mode 100644 index 0000000000..d4bd211a26 --- /dev/null +++ b/src/main/java/wooteco/subway/dao/LineRepositoryImpl.java @@ -0,0 +1,102 @@ +package wooteco.subway.dao; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; +import wooteco.subway.domain.Line; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Optional; + +@Repository +public class LineRepositoryImpl implements LineRepository { + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private final SimpleJdbcInsert simpleJdbcInsert; + + private RowMapper rowMapper() { + return (resultSet, rowNum) -> { + long id = resultSet.getLong("id"); + String name = resultSet.getString("name"); + String color = resultSet.getString("color"); + return new Line(id, name, color); + }; + } + + public LineRepositoryImpl(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + this.simpleJdbcInsert = new SimpleJdbcInsert(dataSource) + .withTableName("line") + .usingGeneratedKeyColumns("id"); + } + + @Override + public Line save(final Line line) { + SqlParameterSource parameters = new MapSqlParameterSource() + .addValue("name", line.getName()) + .addValue("color", line.getColor()); + + long id = simpleJdbcInsert.executeAndReturnKey(parameters).longValue(); + return new Line(id, line.getName(), line.getColor()); + } + + @Override + public List findAll() { + String sql = "SELECT * FROM line"; + return namedParameterJdbcTemplate.query(sql, rowMapper()); + } + + @Override + public Optional findById(final Long id) { + String sql = "SELECT * FROM line WHERE id = :id"; + SqlParameterSource parameters = new MapSqlParameterSource("id", id); + List lines = namedParameterJdbcTemplate.query(sql, parameters, rowMapper()); + return getOptional(lines); + } + + @Override + public Optional findByName(final String name) { + String sql = "SELECT * FROM line WHERE name = :name"; + SqlParameterSource parameters = new MapSqlParameterSource("name", name); + List lines = namedParameterJdbcTemplate.query(sql, parameters, rowMapper()); + return getOptional(lines); + } + + private Optional getOptional(List lines) { + if (lines.isEmpty()) { + return Optional.empty(); + } + return Optional.ofNullable(lines.get(0)); + } + + @Override + public void update(final Long id, final Line line) { + String sql = "UPDATE line SET name = :name, color = :color WHERE id = :id"; + + SqlParameterSource nameParameters = new MapSqlParameterSource() + .addValue("id", id) + .addValue("name", line.getName()) + .addValue("color", line.getColor()); + + namedParameterJdbcTemplate.update(sql, nameParameters); + } + + @Override + public void deleteById(Long id) { + String sql = "DELETE FROM line WHERE id = :id"; + SqlParameterSource parameters = new MapSqlParameterSource("id", id); + namedParameterJdbcTemplate.update(sql, parameters); + } + + @Override + public boolean existByName(String name) { + final String sql = "SELECT COUNT(*) FROM line WHERE name = :name"; + SqlParameterSource parameters = new MapSqlParameterSource("name", name); + Integer count = namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class); + return count != 0; + } +} diff --git a/src/main/java/wooteco/subway/dao/StationDao.java b/src/main/java/wooteco/subway/dao/StationDao.java deleted file mode 100644 index cc1a9f0aa0..0000000000 --- a/src/main/java/wooteco/subway/dao/StationDao.java +++ /dev/null @@ -1,30 +0,0 @@ -package wooteco.subway.dao; - -import org.springframework.util.ReflectionUtils; -import wooteco.subway.domain.Station; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -public class StationDao { - private static Long seq = 0L; - private static List stations = new ArrayList<>(); - - public static Station save(Station station) { - Station persistStation = createNewObject(station); - stations.add(persistStation); - return persistStation; - } - - public static List findAll() { - return stations; - } - - private static Station createNewObject(Station station) { - Field field = ReflectionUtils.findField(Station.class, "id"); - field.setAccessible(true); - ReflectionUtils.setField(field, station, ++seq); - return station; - } -} diff --git a/src/main/java/wooteco/subway/dao/StationRepository.java b/src/main/java/wooteco/subway/dao/StationRepository.java new file mode 100644 index 0000000000..aa1f189388 --- /dev/null +++ b/src/main/java/wooteco/subway/dao/StationRepository.java @@ -0,0 +1,21 @@ +package wooteco.subway.dao; + +import wooteco.subway.domain.Station; + +import java.util.List; +import java.util.Optional; + +public interface StationRepository { + + Station save(final Station station); + + List findAll(); + + void deleteById(Long id); + + Optional findByName(String name); + + Optional findById(Long id); + + boolean existByName(String name); +} diff --git a/src/main/java/wooteco/subway/dao/StationRepositoryImpl.java b/src/main/java/wooteco/subway/dao/StationRepositoryImpl.java new file mode 100644 index 0000000000..a95483eb6d --- /dev/null +++ b/src/main/java/wooteco/subway/dao/StationRepositoryImpl.java @@ -0,0 +1,87 @@ +package wooteco.subway.dao; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; +import wooteco.subway.domain.Station; + +import javax.sql.DataSource; +import java.util.List; +import java.util.Optional; + +@Repository +public class StationRepositoryImpl implements StationRepository { + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private final SimpleJdbcInsert simpleJdbcInsert; + + private RowMapper rowMapper() { + return (resultSet, rowNum) -> { + long id = resultSet.getLong("id"); + String name = resultSet.getString("name"); + return new Station(id, name); + }; + } + + public StationRepositoryImpl(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + this.simpleJdbcInsert = new SimpleJdbcInsert(dataSource) + .withTableName("station") + .usingGeneratedKeyColumns("id"); + } + + @Override + public Station save(final Station station) { + SqlParameterSource parameters = new MapSqlParameterSource() + .addValue("name", station.getName()); + Long id = simpleJdbcInsert.executeAndReturnKey(parameters).longValue(); + return new Station(id, station.getName()); + } + + @Override + public List findAll() { + String sql = "SELECT * FROM station"; + RowMapper stationRowMapper = rowMapper(); + return namedParameterJdbcTemplate.query(sql, stationRowMapper); + } + + @Override + public void deleteById(final Long id) { + String sql = "DELETE FROM station WHERE id = :id"; + namedParameterJdbcTemplate.update(sql, new MapSqlParameterSource("id", id)); + } + + @Override + public Optional findByName(final String name) { + String sql = "SELECT * FROM station WHERE name = :name"; + SqlParameterSource parameters = new MapSqlParameterSource("name", name); + List stations = namedParameterJdbcTemplate.query(sql, parameters, rowMapper()); + return getOptional(stations); + } + + @Override + public Optional findById(Long id) { + String sql = "SELECT * FROM station WHERE id = :id"; + SqlParameterSource parameters = new MapSqlParameterSource("id", id); + List stations = namedParameterJdbcTemplate.query(sql, parameters, rowMapper()); + return getOptional(stations); + } + + private Optional getOptional(List stations) { + if (stations.isEmpty()) { + return Optional.empty(); + } + return Optional.ofNullable(stations.get(0)); + } + + @Override + public boolean existByName(String name) { + final String sql = "SELECT COUNT(*) FROM station WHERE name = :name"; + SqlParameterSource parameters = new MapSqlParameterSource("name", name); + Integer count = namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class); + return count != 0; + } +} diff --git a/src/main/java/wooteco/subway/domain/Line.java b/src/main/java/wooteco/subway/domain/Line.java new file mode 100644 index 0000000000..e296f35a5e --- /dev/null +++ b/src/main/java/wooteco/subway/domain/Line.java @@ -0,0 +1,45 @@ +package wooteco.subway.domain; + +import java.util.Objects; + +public class Line { + + private final Long id; + private final String name; + private final String color; + + public Line(String name, String color) { + this(null, name, color); + } + + public Line(Long id, String name, String color) { + this.id = id; + this.name = name; + this.color = color; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getColor() { + return color; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Line line = (Line) o; + return Objects.equals(name, line.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/src/main/java/wooteco/subway/domain/Station.java b/src/main/java/wooteco/subway/domain/Station.java index c4e86ee9cc..05907cb1bb 100644 --- a/src/main/java/wooteco/subway/domain/Station.java +++ b/src/main/java/wooteco/subway/domain/Station.java @@ -1,10 +1,13 @@ package wooteco.subway.domain; +import java.util.Objects; + public class Station { - private Long id; - private String name; + private final Long id; + private final String name; - public Station() { + public Station(String name) { + this(null, name); } public Station(Long id, String name) { @@ -12,10 +15,6 @@ public Station(Long id, String name) { this.name = name; } - public Station(String name) { - this.name = name; - } - public Long getId() { return id; } @@ -23,5 +22,18 @@ public Long getId() { public String getName() { return name; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Station station = (Station) o; + return Objects.equals(name, station.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } diff --git a/src/main/java/wooteco/subway/dto/ErrorResponse.java b/src/main/java/wooteco/subway/dto/ErrorResponse.java new file mode 100644 index 0000000000..3f2f798ab0 --- /dev/null +++ b/src/main/java/wooteco/subway/dto/ErrorResponse.java @@ -0,0 +1,14 @@ +package wooteco.subway.dto; + +public class ErrorResponse { + + private final String message; + + public ErrorResponse(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/wooteco/subway/dto/LineRequest.java b/src/main/java/wooteco/subway/dto/LineRequest.java index c44e7f3934..a57d57d673 100644 --- a/src/main/java/wooteco/subway/dto/LineRequest.java +++ b/src/main/java/wooteco/subway/dto/LineRequest.java @@ -1,5 +1,7 @@ package wooteco.subway.dto; +import wooteco.subway.domain.Line; + public class LineRequest { private String name; private String color; @@ -7,7 +9,11 @@ public class LineRequest { private Long downStationId; private int distance; - public LineRequest() { + private LineRequest() { + } + + public LineRequest(String name, String color) { + this(name, color, 0L, 0L, 0); } public LineRequest(String name, String color, Long upStationId, Long downStationId, int distance) { @@ -18,6 +24,10 @@ public LineRequest(String name, String color, Long upStationId, Long downStation this.distance = distance; } + public Line toLine() { + return new Line(name, color); + } + public String getName() { return name; } diff --git a/src/main/java/wooteco/subway/dto/LineResponse.java b/src/main/java/wooteco/subway/dto/LineResponse.java index 8bb4be490a..4210f86c75 100644 --- a/src/main/java/wooteco/subway/dto/LineResponse.java +++ b/src/main/java/wooteco/subway/dto/LineResponse.java @@ -1,6 +1,6 @@ package wooteco.subway.dto; -import wooteco.subway.dto.StationResponse; +import wooteco.subway.domain.Line; import java.util.List; @@ -10,6 +10,9 @@ public class LineResponse { private String color; private List stations; + private LineResponse() { + } + public LineResponse(Long id, String name, String color, List stations) { this.id = id; this.name = name; @@ -17,6 +20,12 @@ public LineResponse(Long id, String name, String color, List st this.stations = stations; } + public LineResponse(Line line) { + this.id = line.getId(); + this.name = line.getName(); + this.color = line.getColor(); + } + public Long getId() { return id; } diff --git a/src/main/java/wooteco/subway/dto/SectionRequest.java b/src/main/java/wooteco/subway/dto/SectionRequest.java index 9c3532372b..f674b4a285 100644 --- a/src/main/java/wooteco/subway/dto/SectionRequest.java +++ b/src/main/java/wooteco/subway/dto/SectionRequest.java @@ -5,7 +5,7 @@ public class SectionRequest { private Long downStationId; private int distance; - public SectionRequest() { + private SectionRequest() { } public SectionRequest(Long upStationId, Long downStationId, int distance) { diff --git a/src/main/java/wooteco/subway/dto/StationRequest.java b/src/main/java/wooteco/subway/dto/StationRequest.java index ada674ad31..135202c55f 100644 --- a/src/main/java/wooteco/subway/dto/StationRequest.java +++ b/src/main/java/wooteco/subway/dto/StationRequest.java @@ -3,7 +3,7 @@ public class StationRequest { private String name; - public StationRequest() { + private StationRequest() { } public StationRequest(String name) { diff --git a/src/main/java/wooteco/subway/dto/StationResponse.java b/src/main/java/wooteco/subway/dto/StationResponse.java index 35a6142d70..34636b066a 100644 --- a/src/main/java/wooteco/subway/dto/StationResponse.java +++ b/src/main/java/wooteco/subway/dto/StationResponse.java @@ -1,15 +1,17 @@ package wooteco.subway.dto; +import wooteco.subway.domain.Station; + public class StationResponse { private Long id; private String name; - public StationResponse() { + private StationResponse() { } - public StationResponse(Long id, String name) { - this.id = id; - this.name = name; + public StationResponse(Station station) { + this.id = station.getId(); + this.name = station.getName(); } public Long getId() { diff --git a/src/main/java/wooteco/subway/service/LineService.java b/src/main/java/wooteco/subway/service/LineService.java new file mode 100644 index 0000000000..5e86ad30aa --- /dev/null +++ b/src/main/java/wooteco/subway/service/LineService.java @@ -0,0 +1,59 @@ +package wooteco.subway.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import wooteco.subway.dao.LineRepository; +import wooteco.subway.domain.Line; +import wooteco.subway.dto.LineRequest; +import wooteco.subway.dto.LineResponse; +import wooteco.subway.utils.exception.NameDuplicatedException; +import wooteco.subway.utils.exception.NotFoundException; + +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +@Service +public class LineService { + + private final LineRepository lineRepository; + + public LineService(LineRepository lineRepository) { + this.lineRepository = lineRepository; + } + + public LineResponse create(final LineRequest lineRequest) { + validateDuplicatedName(lineRequest); + Line savedLine = lineRepository.save(lineRequest.toLine()); + + return new LineResponse(savedLine); + } + + private void validateDuplicatedName(LineRequest lineRequest) { + if (lineRepository.existByName(lineRequest.getName())) { + throw new NameDuplicatedException("[ERROR] ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋…ธ์„ ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค."); + } + } + + public List showLines() { + List lines = lineRepository.findAll(); + return lines.stream() + .map(LineResponse::new) + .collect(Collectors.toList()); + } + + public LineResponse showLine(final Long id) { + Line line = lineRepository.findById(id) + .orElseThrow(() -> new NotFoundException("[ERROR] ํ•ด๋‹นํ•˜๋Š” ์‹๋ณ„์ž์˜ ๋…ธ์„ ์„ ์ฐพ์„์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")); + + return new LineResponse(line); + } + + public void update(final Long id, final LineRequest lineRequest) { + lineRepository.update(id, lineRequest.toLine()); + } + + public void delete(final Long id) { + lineRepository.deleteById(id); + } +} diff --git a/src/main/java/wooteco/subway/service/StationService.java b/src/main/java/wooteco/subway/service/StationService.java new file mode 100644 index 0000000000..edf5ed65dd --- /dev/null +++ b/src/main/java/wooteco/subway/service/StationService.java @@ -0,0 +1,47 @@ +package wooteco.subway.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import wooteco.subway.dao.StationRepository; +import wooteco.subway.domain.Station; +import wooteco.subway.dto.StationRequest; +import wooteco.subway.dto.StationResponse; +import wooteco.subway.utils.exception.NameDuplicatedException; + +import java.util.List; +import java.util.stream.Collectors; + +@Transactional +@Service +public class StationService { + + private final StationRepository stationRepository; + + public StationService(StationRepository stationRepository) { + this.stationRepository = stationRepository; + } + + public StationResponse save(final StationRequest stationRequest) { + validateDuplicateName(stationRequest); + Station saveStation = stationRepository.save(new Station(stationRequest.getName())); + + return new StationResponse(saveStation); + } + + private void validateDuplicateName(StationRequest stationRequest) { + if (stationRepository.existByName(stationRequest.getName())) { + throw new NameDuplicatedException("[ERROR] ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์—ญ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค."); + } + } + + @Transactional(readOnly = true) + public List showStations() { + return stationRepository.findAll().stream() + .map(StationResponse::new) + .collect(Collectors.toList()); + } + + public void deleteStation(final Long id) { + stationRepository.deleteById(id); + } +} diff --git a/src/main/java/wooteco/subway/ui/ControllerAdvice.java b/src/main/java/wooteco/subway/ui/ControllerAdvice.java new file mode 100644 index 0000000000..d9fbdf4185 --- /dev/null +++ b/src/main/java/wooteco/subway/ui/ControllerAdvice.java @@ -0,0 +1,28 @@ +package wooteco.subway.ui; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import wooteco.subway.dto.ErrorResponse; +import wooteco.subway.utils.exception.NameDuplicatedException; +import wooteco.subway.utils.exception.NotFoundException; + +@RestControllerAdvice +public class ControllerAdvice { + + @ExceptionHandler(NameDuplicatedException.class) + public ResponseEntity nameDuplicatedExceptionHandler(NameDuplicatedException e) { + return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage())); + } + + @ExceptionHandler(NotFoundException.class) + public ResponseEntity notFoundExceptionHandler(NotFoundException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(e.getMessage())); + } + + @ExceptionHandler({RuntimeException.class, Exception.class}) + public ResponseEntity serverExceptionHandler() { + return ResponseEntity.internalServerError().build(); + } +} diff --git a/src/main/java/wooteco/subway/ui/LineController.java b/src/main/java/wooteco/subway/ui/LineController.java new file mode 100644 index 0000000000..02660d4dd5 --- /dev/null +++ b/src/main/java/wooteco/subway/ui/LineController.java @@ -0,0 +1,49 @@ +package wooteco.subway.ui; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import wooteco.subway.dto.LineRequest; +import wooteco.subway.dto.LineResponse; +import wooteco.subway.service.LineService; + +import java.net.URI; +import java.util.List; + +@RestController +@RequestMapping("/lines") +public class LineController { + + private final LineService lineService; + + public LineController(LineService lineService) { + this.lineService = lineService; + } + + @PostMapping + public ResponseEntity createLine(@RequestBody LineRequest lineRequest) { + LineResponse lineResponse = lineService.create(lineRequest); + return ResponseEntity.created(URI.create("/lines/" + lineResponse.getId())).body(lineResponse); + } + + @GetMapping + public ResponseEntity> showLines() { + return ResponseEntity.ok(lineService.showLines()); + } + + @GetMapping("/{id}") + public ResponseEntity showLine(@PathVariable Long id) { + return ResponseEntity.ok(lineService.showLine(id)); + } + + @PutMapping("/{id}") + public ResponseEntity updateLine(@PathVariable Long id, @RequestBody LineRequest lineRequest) { + lineService.update(id, lineRequest); + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteLine(@PathVariable Long id) { + lineService.delete(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/wooteco/subway/ui/StationController.java b/src/main/java/wooteco/subway/ui/StationController.java index 892ccbce4a..2b8e955413 100644 --- a/src/main/java/wooteco/subway/ui/StationController.java +++ b/src/main/java/wooteco/subway/ui/StationController.java @@ -1,39 +1,37 @@ package wooteco.subway.ui; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import wooteco.subway.dao.StationDao; -import wooteco.subway.domain.Station; import wooteco.subway.dto.StationRequest; import wooteco.subway.dto.StationResponse; +import wooteco.subway.service.StationService; import java.net.URI; import java.util.List; -import java.util.stream.Collectors; @RestController public class StationController { + private final StationService stationService; + + public StationController(StationService stationService) { + this.stationService = stationService; + } + @PostMapping("/stations") public ResponseEntity createStation(@RequestBody StationRequest stationRequest) { - Station station = new Station(stationRequest.getName()); - Station newStation = StationDao.save(station); - StationResponse stationResponse = new StationResponse(newStation.getId(), newStation.getName()); - return ResponseEntity.created(URI.create("/stations/" + newStation.getId())).body(stationResponse); + StationResponse stationResponse = stationService.save(stationRequest); + return ResponseEntity.created(URI.create("/stations/" + stationResponse.getId())).body(stationResponse); } - @GetMapping(value = "/stations", produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping("/stations") public ResponseEntity> showStations() { - List stations = StationDao.findAll(); - List stationResponses = stations.stream() - .map(it -> new StationResponse(it.getId(), it.getName())) - .collect(Collectors.toList()); - return ResponseEntity.ok().body(stationResponses); + return ResponseEntity.ok().body(stationService.showStations()); } @DeleteMapping("/stations/{id}") public ResponseEntity deleteStation(@PathVariable Long id) { + stationService.deleteStation(id); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/wooteco/subway/utils/exception/NameDuplicatedException.java b/src/main/java/wooteco/subway/utils/exception/NameDuplicatedException.java new file mode 100644 index 0000000000..48af6b605c --- /dev/null +++ b/src/main/java/wooteco/subway/utils/exception/NameDuplicatedException.java @@ -0,0 +1,7 @@ +package wooteco.subway.utils.exception; + +public class NameDuplicatedException extends RuntimeException { + public NameDuplicatedException(String message) { + super(message); + } +} diff --git a/src/main/java/wooteco/subway/utils/exception/NotFoundException.java b/src/main/java/wooteco/subway/utils/exception/NotFoundException.java new file mode 100644 index 0000000000..b7c84e5269 --- /dev/null +++ b/src/main/java/wooteco/subway/utils/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package wooteco.subway.utils.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 0000000000..4c920467d7 --- /dev/null +++ b/src/main/resources/application-test.yml @@ -0,0 +1,9 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:atestdb + username: sa + password: + h2: + console: + enabled: true diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000..0307b30b90 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:testdb + username: sa + password: + h2: + console: + enabled: true diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..4cade82ba4 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,17 @@ +drop table if exists STATION; +drop table if exists LINE; + +create table STATION +( + id bigint auto_increment not null, + name varchar(255) not null unique, + primary key(id) +); + +create table LINE +( + id bigint auto_increment not null, + name varchar(255) not null unique, + color varchar(20) not null, + primary key(id) +); diff --git a/src/test/java/wooteco/subway/SubwayApplicationTests.java b/src/test/java/wooteco/subway/SubwayApplicationTests.java deleted file mode 100644 index 387ed68012..0000000000 --- a/src/test/java/wooteco/subway/SubwayApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package wooteco.subway; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SubwayApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/wooteco/subway/acceptance/AcceptanceTest.java b/src/test/java/wooteco/subway/acceptance/AcceptanceTest.java index 1fd156022f..4505c6f06f 100644 --- a/src/test/java/wooteco/subway/acceptance/AcceptanceTest.java +++ b/src/test/java/wooteco/subway/acceptance/AcceptanceTest.java @@ -5,7 +5,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +@ActiveProfiles("test") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class AcceptanceTest { diff --git a/src/test/java/wooteco/subway/acceptance/LineAcceptanceTest.java b/src/test/java/wooteco/subway/acceptance/LineAcceptanceTest.java new file mode 100644 index 0000000000..58e44e7bd3 --- /dev/null +++ b/src/test/java/wooteco/subway/acceptance/LineAcceptanceTest.java @@ -0,0 +1,184 @@ +package wooteco.subway.acceptance; + +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import wooteco.subway.dto.LineRequest; +import wooteco.subway.dto.LineResponse; + +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.junit.jupiter.api.Assertions.assertAll; + +@DisplayName("๋…ธ์„  ๊ด€๋ จ ๊ธฐ๋Šฅ") +public class LineAcceptanceTest extends AcceptanceTest { + + private static final LineRequest BODY = new LineRequest("์‹ ๋ถ„๋‹น์„ ", "bg-red-600"); + + @DisplayName("๋…ธ์„ ์„ ์ƒ์„ฑํ•˜๋ฉด 201 created๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  Location header์— url resource๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void createLine() { + // when + ExtractableResponse response = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + assertThat(response.header("Location")).isNotBlank(); + } + + @DisplayName("๊ธฐ์กด์— ์กด์žฌํ•˜๋Š” ๋…ธ์„  ์ด๋ฆ„์œผ๋กœ ๋…ธ์„ ์„ ์ƒ์„ฑํ•˜๋ฉด 400 bad-request๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void createLineWithDuplicateName() { + + RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all(); + + ExtractableResponse response = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + } + + @DisplayName("์ „์ฒด ๋…ธ์„ ์„ ์กฐํšŒํ•˜๋ฉด 200 ok์™€ ๋…ธ์„  ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void getLines() { + + ExtractableResponse newBundangPostResponse = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + LineRequest request = new LineRequest("๋ถ„๋‹น์„ ", "bg-green-600"); + + ExtractableResponse bundangPostResponse = RestAssured.given().log().all() + .body(request) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + ExtractableResponse response = RestAssured.given().log().all() + .when() + .get("/lines") + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + + List expectedLineIds = Stream.of(newBundangPostResponse, bundangPostResponse) + .map(it -> Long.parseLong(it.header("Location").split("/")[2])) + .collect(Collectors.toList()); + List responses = response.jsonPath().getList(".", LineResponse.class); + + List ids = responses.stream().map(LineResponse::getId).collect(Collectors.toList()); + + assertAll( + () -> assertThat(ids).containsAll(expectedLineIds), + () -> assertThat(responses.get(0).getName()).isEqualTo("์‹ ๋ถ„๋‹น์„ "), + () -> assertThat(responses.get(0).getColor()).isEqualTo("bg-red-600"), + () -> assertThat(responses.get(1).getName()).isEqualTo("๋ถ„๋‹น์„ "), + () -> assertThat(responses.get(1).getColor()).isEqualTo("bg-green-600") + ); + } + + @DisplayName("๋‹จ๊ฑด ๋…ธ์„ ์„ ์กฐํšŒํ•˜๋ฉด 200 OK์™€ ๋…ธ์„  ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค") + @Test + void getLine() { + + ExtractableResponse createResponse = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + long id = Long.parseLong(createResponse.header(HttpHeaders.LOCATION).split("/")[2]); + + ExtractableResponse getResponse = RestAssured.given().log().all() + .when() + .get("/lines/" + id) + .then().log().all() + .extract(); + + long responseId = getResponse.jsonPath().getLong("id"); + assertThat(id).isEqualTo(responseId); + } + + @DisplayName("๋…ธ์„ ์„ ์ˆ˜์ •ํ•˜๋ฉด 200 OK๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void updateLine() { + + ExtractableResponse createResponse = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + long id = Long.parseLong(createResponse.header(HttpHeaders.LOCATION).split("/")[2]); + + LineRequest request = new LineRequest("๋‹ค๋ฅธ๋ถ„๋‹น์„ ", "bg-red-600"); + + ExtractableResponse response = RestAssured.given().log().all() + .body(request) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .put("/lines/" + id) + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + + @DisplayName("๋…ธ์„ ์„ ์ œ๊ฑฐํ•˜๋ฉด 204 No Content๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void deleteStation() { + + ExtractableResponse createResponse = RestAssured.given().log().all() + .body(BODY) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when() + .post("/lines") + .then().log().all() + .extract(); + + String uri = createResponse.header("Location"); + ExtractableResponse response = RestAssured.given().log().all() + .when() + .delete(uri) + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(HttpStatus.NO_CONTENT.value()); + } + +} diff --git a/src/test/java/wooteco/subway/acceptance/StationAcceptanceTest.java b/src/test/java/wooteco/subway/acceptance/StationAcceptanceTest.java index a5cf0d2583..50f87c947f 100644 --- a/src/test/java/wooteco/subway/acceptance/StationAcceptanceTest.java +++ b/src/test/java/wooteco/subway/acceptance/StationAcceptanceTest.java @@ -7,29 +7,27 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import wooteco.subway.acceptance.AcceptanceTest; +import wooteco.subway.dto.StationRequest; import wooteco.subway.dto.StationResponse; -import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; @DisplayName("์ง€ํ•˜์ฒ ์—ญ ๊ด€๋ จ ๊ธฐ๋Šฅ") public class StationAcceptanceTest extends AcceptanceTest { + + private static final StationRequest BODY = new StationRequest("๊ฐ•๋‚จ์—ญ"); + @DisplayName("์ง€ํ•˜์ฒ ์—ญ์„ ์ƒ์„ฑํ•œ๋‹ค.") @Test void createStation() { - // given - Map params = new HashMap<>(); - params.put("name", "๊ฐ•๋‚จ์—ญ"); - // when ExtractableResponse response = RestAssured.given().log().all() - .body(params) + .body(BODY) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") @@ -44,11 +42,8 @@ void createStation() { @DisplayName("๊ธฐ์กด์— ์กด์žฌํ•˜๋Š” ์ง€ํ•˜์ฒ ์—ญ ์ด๋ฆ„์œผ๋กœ ์ง€ํ•˜์ฒ ์—ญ์„ ์ƒ์„ฑํ•œ๋‹ค.") @Test void createStationWithDuplicateName() { - // given - Map params = new HashMap<>(); - params.put("name", "๊ฐ•๋‚จ์—ญ"); RestAssured.given().log().all() - .body(params) + .body(BODY) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") @@ -57,7 +52,7 @@ void createStationWithDuplicateName() { // when ExtractableResponse response = RestAssured.given().log().all() - .body(params) + .body(BODY) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") @@ -73,20 +68,16 @@ void createStationWithDuplicateName() { @Test void getStations() { /// given - Map params1 = new HashMap<>(); - params1.put("name", "๊ฐ•๋‚จ์—ญ"); ExtractableResponse createResponse1 = RestAssured.given().log().all() - .body(params1) + .body(BODY) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") .then().log().all() .extract(); - - Map params2 = new HashMap<>(); - params2.put("name", "์—ญ์‚ผ์—ญ"); + StationRequest request = new StationRequest("์—ญ์‚ผ์—ญ"); ExtractableResponse createResponse2 = RestAssured.given().log().all() - .body(params2) + .body(request) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") @@ -102,23 +93,27 @@ void getStations() { // then assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); - List expectedLineIds = Arrays.asList(createResponse1, createResponse2).stream() + List expectedLineIds = Stream.of(createResponse1, createResponse2) .map(it -> Long.parseLong(it.header("Location").split("/")[2])) .collect(Collectors.toList()); - List resultLineIds = response.jsonPath().getList(".", StationResponse.class).stream() - .map(it -> it.getId()) - .collect(Collectors.toList()); - assertThat(resultLineIds).containsAll(expectedLineIds); + List responses = response.jsonPath().getList(".", StationResponse.class); + + List ids = responses.stream().map(StationResponse::getId).collect(Collectors.toList()); + + assertAll( + () -> assertThat(ids).containsAll(expectedLineIds), + () -> assertThat(responses.get(0).getName()).isEqualTo("๊ฐ•๋‚จ์—ญ"), + () -> assertThat(responses.get(1).getName()).isEqualTo("์—ญ์‚ผ์—ญ") + ); + } @DisplayName("์ง€ํ•˜์ฒ ์—ญ์„ ์ œ๊ฑฐํ•œ๋‹ค.") @Test void deleteStation() { // given - Map params = new HashMap<>(); - params.put("name", "๊ฐ•๋‚จ์—ญ"); ExtractableResponse createResponse = RestAssured.given().log().all() - .body(params) + .body(BODY) .contentType(MediaType.APPLICATION_JSON_VALUE) .when() .post("/stations") diff --git a/src/test/java/wooteco/subway/dao/LineRepositoryTest.java b/src/test/java/wooteco/subway/dao/LineRepositoryTest.java new file mode 100644 index 0000000000..ab16d257f1 --- /dev/null +++ b/src/test/java/wooteco/subway/dao/LineRepositoryTest.java @@ -0,0 +1,104 @@ +package wooteco.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.JdbcTest; +import wooteco.subway.domain.Line; + +import javax.sql.DataSource; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +@JdbcTest +public class LineRepositoryTest { + + @Autowired + private DataSource dataSource; + + private LineRepository lineRepository; + + @BeforeEach + void setUp() { + lineRepository = new LineRepositoryImpl(dataSource); + } + + @DisplayName("๋…ธ์„ ์„ ์ €์žฅํ•œ๋‹ค.") + @Test + void save() { + Line line = new Line("๋ถ„๋‹น์„ ", "bg-red-600"); + Line saveLine = lineRepository.save(line); + + assertAll( + () -> assertThat(saveLine.getId()).isNotNull(), + () -> assertThat(saveLine).isEqualTo(line) + ); + } + + @DisplayName("๋ชจ๋“  ๋…ธ์„ ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findAll() { + Line line1 = new Line("๋ถ„๋‹น์„ ", "bg-red-600"); + Line saveLine1 = lineRepository.save(line1); + Line line2 = new Line("์‹ ๋ถ„๋‹น์„ ", "bg-red-600"); + Line saveLine2 = lineRepository.save(line2); + + List lines = lineRepository.findAll(); + + assertAll( + () -> assertThat(lines).hasSize(2), + () -> assertThat(lines).containsExactly(saveLine1, saveLine2) + ); + } + + @DisplayName("์‹๋ณ„์ž๋กœ ๋…ธ์„ ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findById() { + Line saveLine = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + Line findLine = lineRepository.findById(saveLine.getId()).get(); + + assertThat(findLine).isEqualTo(saveLine); + } + + @DisplayName("์ด๋ฆ„์œผ๋กœ ๋…ธ์„ ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findByName() { + Line saveLine = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + Line findLine = lineRepository.findByName("๋ถ„๋‹น์„ ").get(); + + assertThat(findLine).isEqualTo(saveLine); + } + + @DisplayName("๋™์ผํ•œ ์ด๋ฆ„์˜ ๋…ธ์„ ์ด ์กด์žฌํ•  ๊ฒฝ์šฐ true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void existByName() { + lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + assertThat(lineRepository.existByName("๋ถ„๋‹น์„ ")).isTrue(); + } + + @DisplayName("๋…ธ์„ ์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void update() { + Line saveLine = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + Line updatedLine = new Line("์‹ ๋ถ„๋‹น์„ ", "bg-yellow-600"); + lineRepository.update(saveLine.getId(), updatedLine); + Line findUpdateLine = lineRepository.findById(saveLine.getId()).get(); + + assertAll( + () -> assertThat(findUpdateLine.getName()).isEqualTo(updatedLine.getName()), + () -> assertThat(findUpdateLine.getColor()).isEqualTo(updatedLine.getColor()) + ); + } + + @DisplayName("๋…ธ์„ ์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteById() { + Line saveLine = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + lineRepository.deleteById(saveLine.getId()); + + assertThat(lineRepository.findAll()).isEmpty(); + } +} diff --git a/src/test/java/wooteco/subway/dao/StationRepositoryTest.java b/src/test/java/wooteco/subway/dao/StationRepositoryTest.java new file mode 100644 index 0000000000..d12acee2fd --- /dev/null +++ b/src/test/java/wooteco/subway/dao/StationRepositoryTest.java @@ -0,0 +1,88 @@ +package wooteco.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.JdbcTest; +import wooteco.subway.domain.Station; + +import javax.sql.DataSource; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +@JdbcTest +class StationRepositoryTest { + + @Autowired + private DataSource dataSource; + + private StationRepository stationRepository; + private static final String SILLIM_STATION = "์‹ ๋ฆผ์—ญ"; + + @BeforeEach + void setUp() { + stationRepository = new StationRepositoryImpl(dataSource); + } + + @DisplayName("์—ญ์„ ์ €์žฅํ•œ๋‹ค.") + @Test + void save() { + Station station = new Station(SILLIM_STATION); + Station saveStation = stationRepository.save(station); + + assertAll( + () -> assertThat(saveStation.getId()).isNotNull(), + () -> assertThat(saveStation).isEqualTo(station) + ); + } + + @DisplayName("๋ชจ๋“  ์—ญ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findAll() { + Station station1 = new Station(SILLIM_STATION); + stationRepository.save(station1); + Station station2 = new Station("์‹ ๋Œ€๋ฐฉ์—ญ"); + stationRepository.save(station2); + + List stations = stationRepository.findAll(); + + assertAll( + () -> assertThat(stations).hasSize(2), + () -> assertThat(stations).containsExactly(station1, station2) + ); + } + + @DisplayName("์—ญ์„ ์‚ญ์ œํ•œ๋‹ค") + @Test + void deleteById() { + Station saveStation = stationRepository.save(new Station(SILLIM_STATION)); + stationRepository.deleteById(saveStation.getId()); + + assertThat(stationRepository.findAll()).isEmpty(); + } + + @DisplayName("์ด๋ฆ„์œผ๋กœ ์—ญ์ด ์กด์žฌํ•˜๋Š”์ง€ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findByName() { + stationRepository.save(new Station(SILLIM_STATION)); + Station station = stationRepository.findByName(SILLIM_STATION).get(); + assertThat(station.getName()).isEqualTo(SILLIM_STATION); + } + + @DisplayName("id๋กœ ์—ญ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findById() { + Station saveStation = stationRepository.save(new Station(SILLIM_STATION)); + assertThat(stationRepository.findById(saveStation.getId())).isNotNull(); + } + + @DisplayName("๋™์ผํ•œ ์ด๋ฆ„์˜ ์—ญ์ด ์กด์žฌํ•  ๊ฒฝ์šฐ true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + @Test + void existByName() { + stationRepository.save(new Station(SILLIM_STATION)); + assertThat(stationRepository.existByName(SILLIM_STATION)).isTrue(); + } +} diff --git a/src/test/java/wooteco/subway/service/LineServiceTest.java b/src/test/java/wooteco/subway/service/LineServiceTest.java new file mode 100644 index 0000000000..a7c4cef800 --- /dev/null +++ b/src/test/java/wooteco/subway/service/LineServiceTest.java @@ -0,0 +1,103 @@ +package wooteco.subway.service; + +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.JdbcTest; +import wooteco.subway.dao.LineRepository; +import wooteco.subway.dao.LineRepositoryImpl; +import wooteco.subway.domain.Line; +import wooteco.subway.dto.LineRequest; +import wooteco.subway.dto.LineResponse; +import wooteco.subway.utils.exception.NameDuplicatedException; + +import javax.sql.DataSource; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +@JdbcTest +public class LineServiceTest { + + @Autowired + private DataSource dataSource; + + private LineService lineService; + private LineRepository lineRepository; + + @BeforeEach + void setUp() { + lineRepository = new LineRepositoryImpl(dataSource); + lineService = new LineService(lineRepository); + } + + @DisplayName("๋…ธ์„ ์„ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void create() { + LineRequest lineRequest = new LineRequest("๋ถ„๋‹น์„ ", "bg-red-600"); + LineResponse lineResponse = lineService.create(lineRequest); + + assertAll( + () -> assertThat(lineResponse.getId()).isNotNull(), + () -> assertThat(lineResponse.getName()).isEqualTo(lineRequest.getName()), + () -> assertThat(lineResponse.getColor()).isEqualTo(lineRequest.getColor()) + ); + } + + @DisplayName("๋…ธ์„  ์ƒ์„ฑ์‹œ ์ด๋ฆ„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ์˜ˆ์™ธ ๋ฐœ์ƒ") + @Test + void createDuplicateName() { + lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + assertThatThrownBy(() -> lineService.create(new LineRequest("๋ถ„๋‹น์„ ", "bg-red-600"))) + .isInstanceOf(NameDuplicatedException.class); + } + + @DisplayName("๋ชจ๋“  ๋…ธ์„ ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void showLines() { + lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + lineRepository.save(new Line("์‹ ๋ถ„๋‹น์„ ", "bg-yellow-600")); + + List lineResponses = lineService.showLines(); + assertThat(lineResponses).hasSize(2); + } + + @DisplayName("๋…ธ์„ ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void showLine() { + Line line = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + LineResponse lineResponse = lineService.showLine(line.getId()); + + assertAll( + () -> assertThat(lineResponse.getName()).isEqualTo("๋ถ„๋‹น์„ "), + () -> assertThat(lineResponse.getColor()).isEqualTo("bg-red-600") + ); + } + + @DisplayName("๋…ธ์„ ์„ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.") + @Test + void update() { + Line line = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + lineService.update(line.getId(), new LineRequest("์‹ ๋ถ„๋‹น์„ ", "bg-yellow-600")); + + Line findUpdateLine = lineRepository.findById(line.getId()).get(); + assertAll( + () -> assertThat(findUpdateLine.getName()).isEqualTo("์‹ ๋ถ„๋‹น์„ "), + () -> assertThat(findUpdateLine.getColor()).isEqualTo("bg-yellow-600") + ); + } + + + @DisplayName("๋…ธ์„ ์„ ์ œ๊ฑฐ ํ•œ๋‹ค.") + @Test + void delete() { + Line line = lineRepository.save(new Line("๋ถ„๋‹น์„ ", "bg-red-600")); + lineService.delete(line.getId()); + + assertThat(lineRepository.findAll()).isEmpty(); + } + +} diff --git a/src/test/java/wooteco/subway/service/StationServiceTest.java b/src/test/java/wooteco/subway/service/StationServiceTest.java new file mode 100644 index 0000000000..f4c4c2d5e0 --- /dev/null +++ b/src/test/java/wooteco/subway/service/StationServiceTest.java @@ -0,0 +1,71 @@ +package wooteco.subway.service; + +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.JdbcTest; +import wooteco.subway.dao.StationRepository; +import wooteco.subway.dao.StationRepositoryImpl; +import wooteco.subway.domain.Station; +import wooteco.subway.dto.StationRequest; +import wooteco.subway.dto.StationResponse; +import wooteco.subway.utils.exception.NameDuplicatedException; + +import javax.sql.DataSource; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@JdbcTest +class StationServiceTest { + + @Autowired + private DataSource dataSource; + + private StationService stationService; + private StationRepository stationRepository; + + @BeforeEach + void setUp() { + stationRepository = new StationRepositoryImpl(dataSource); + stationService = new StationService(stationRepository); + } + + @DisplayName("์—ญ ์š”์ฒญ์„ ๋ฐ›์•„ ์ €์žฅํ•œ๋‹ค.") + @Test + void save() { + StationResponse stationResponse = stationService.save(new StationRequest("์‹ ๋ฆผ์—ญ")); + Station findStation = stationRepository.findById(stationResponse.getId()).get(); + + assertThat(stationResponse.getId()).isEqualTo(findStation.getId()); + } + + @DisplayName("๋™์ผํ•œ ์ด๋ฆ„์˜ ์—ญ์ด ์žˆ์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void saveDuplicateName() { + stationRepository.save(new Station("์‹ ๋ฆผ์—ญ")); + assertThatThrownBy( + () -> stationService.save(new StationRequest("์‹ ๋ฆผ์—ญ")) + ).isInstanceOf(NameDuplicatedException.class); + } + + @DisplayName("๋ชจ๋“  ์—ญ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void showStations() { + stationRepository.save(new Station("์‹ ๋ฆผ์—ญ")); + stationRepository.save(new Station("์‹ ๋Œ€๋ฐฉ์—ญ")); + List stationResponses = stationService.showStations(); + assertThat(stationResponses).hasSize(2); + } + + @DisplayName("์—ญ์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteStation() { + Station station = stationRepository.save(new Station("์‹ ๋ฆผ์—ญ")); + stationService.deleteStation(station.getId()); + assertThat(stationRepository.findById(station.getId())).isEmpty(); + } + +}