์ค๋ณต๋๋ ํ ์คํธ ๋ฉ์๋
- ์ค๋ณต๋๋ ํ ์คํธ ๋ฉ์๋๋ ์ถ์ถํ์
- ํ ์คํธ์ฝ๋๋ ์ ์ง๋ณด์์ ๋์์ด๋ฉฐ ํ๋์ ๋ฌธ์์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ์ฑ์ ๊ณ ๋ คํ์
private ExtractableResponse<Response> addSection(String content) {
return RestAssured.given().log().all()
.body(content)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.when()
.post("/lines/{id}/sections", 1L)
.then().log().all()
.extract();
}
์์ธ ์ฒ๋ฆฌ๋ Service์์
- DAO์์ ์์ธ๋ฅผ ์ฒดํฌํด์ฃผ๊ณ ์์์
- DAO๋ ๋ง๊ทธ๋๋ก DB์ ์ด์ธ์คํ๋ ์ญํ ๋ง ํ ๋ฟ
- ์ด ๊ฒฐ๊ณผ์ ๋ํ ์์ธ๋ ์๋น์ค๊ฐ ์์์ ํ๋๋ก ํ์
@Valid์ @Validated๋ก DTO ๊ฒ์ฆ
@Valid
๋ฅผ ํตํด DTO์์ ์์ฒญ์ ๋ํ ๊ฒ์ฆ์ ํ๊ฒ ํด์ค- Validation์ groupํ ํ ์ ์๋ ์ ์ ์ด์ฉํด์ ๊ฐ๊ธฐ ์์ฒญ๋ง๋ค group์ ์ง์ด ํ DTO๋ฅผ ์ฌ์ฉํด๋ ๊ฐ๊ฐ ์์ฒญ์ ๋ง๋ ๊ฒ์ฆ์ ์งํ
์ ๋ฆฌ
Valid๋ก ์ก์ ์์ธ ๋ฉ์์ง ์ฒ๋ฆฌ
- Valid ์ด๋ ธํ ์ด์ ์ผ๋ก ์ก์ MethodArgumentNotValidException์ ๋ฉ์์ง๋ฅผ ์ ๋๋ก ์ถ๋ ฅํ๊ณ ์์ง ์์์
- ๊ฒ์ด์ธ ๊ฐ ์ ์ํด์ค ๋ฐฉ๋ฒ์ ์ ์ฉํ๋ BindingResult์ ์๋ ์์ธ ๋ฉ์์ง๋ค์ ์ถ์ถํ์ฌ ๋์ ธ์ค ์ ์์์
Service ๋ ์ด์ด์์ ๋๋ฉ์ธ์ด ์๋ DTO๋ฅผ ๋ฐํํ์
- Controller์์ ๋๋ฉ์ธ์ ๊ฐ์ ธ๋ค ์จ์ ํ๋ฉด์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ํํํ๊ธฐ ์ํด ๋๋ฉ์ธ ์์ฒด๋ ๋๋ฉ์ธ์ getter๋ฅผ ๋ ธ์ถ์ํค๊ณ ์์์
- ๋๋ฉ์ธ์ ์ ๋ณด๋ฅผ ์ธ๋ถ(view)์ ๋ ธ์ถํ๋ ๊ฒฝ์ฐ, interface์ธ DTO๋ฅผ ํตํด ์๋น์ค ๋ ์ด์ด์์ ๋ฐํํ๋๋ก ๋ฆฌํฉํ ๋ง
- ์ฐธ๊ณ
์ ๋ฆฌ
RestAssured์ ๋ํด
- ์ ๋จ๊ณ๊น์ง๋ MockMVC ๋ฑ์ผ๋ก ์ปจํธ๋กค๋ฌ๋จ์ ๋จ์ํ ์คํธ๋ก ์งํํ์
- E2E ํ
์คํธ๋ฅผ ํ๋ค๋ ๊ฒ์ ๋ง ๊ทธ๋๋ก ๋๋ถํฐ ๋๊น์ง,์์ฒญ๋ถํฐ ๋ด๊ฐ ์ํ๋ ์๋ต์ ํ
์คํธ ํ๋ ๊ฒ์ธ๋ฐ
์ด๋ ๊ฒ๋๋ฉด ๋จ์ ํ ์คํธ๋ฅผ ํ๋ ์ด์ ๊ฐ ์์๊น๋ผ๋ ๊ณ ๋ฏผ์ ํ์ - ๊ณ ๋ฏผํ ๊ฒฐ๊ณผ โ๋จ์ ํ ์คํธ๋ ๊ตฌํ ๋จ๊ณ์์ ๋ด๊ฐ ๊ตฌํํ ๋ ์ด์ด(๋จ์)๊ฐ ์ ์ ๋์ํ๋์ง๋ฅผ ํ ์คํธํ๊ธฐ ์ํด, ์ดํ ๋ชจ๋ ๋จ์๋ค์ด ์กฐํฉ๋์์ ๋ ํตํฉํ ์คํธ๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ํ๋ ๊ธฐ๋ฅ์ ์ ์ํํ๋์ง ํ ์คํธํ๋คโ ์ด๋ ๊ฒ ๊ฒฐ๋ก ์ ๋ด๋ฆผ
๊ตฌ๊ฐ ์ถ๊ฐ ๋ก์ง
- ๊ตฌ๊ฐ์ ์ถ๊ฐํ ๋ ์ํ์ญ, ํํ์ญ์ด ์กด์ฌํ๋์ง ๋ ์ด๋ฅผ ์ฐพ๊ณ ์์ ํด์ฃผ๊ธฐ ์ํ ๋ง์ ๋ก์ง์ ์์ฑํด์ผํ์
- ๊ทธ๋ฐ๋ฐ ์ฌ์ค ๋น์ทํ ๋ก์ง์ธ๋ฐ ์ํ์ธ์ง ํํ์ธ์ง ๋์๋ง ๋ฌ๋์
- ์๋์ ๊ฐ์ด ์ผ๋จ ๊ตฌํ์ ๋ชฉ์ ์ผ๋ก ํ์ ๋๋ ์์ฒญ๋ ๋ถ๊ธฐ๊ฐ ์๊ฒจ๋ฒ๋ฆผ
@Transactional
public void addSection(final Long lineId, final SectionRequest sectionRequest) {
Line line = lineRepository.findById(lineId);
Section toAddSection = sectionRequest.toSection(lineId);
Station targetStation = line.registeredStation(toAddSection);
if (toAddSection.hasUpStation(targetStation)) {
Section targetSection = line.findSectionWithUpStation(targetStation);
checkAddableByDistance(toAddSection, targetSection);
lineRepository.updateSection(lineId,
new Section(targetSection.id(), lineId, toAddSection.downStation(), targetSection.downStation(), targetSection.subtractDistance(toAddSection)));
}
if (toAddSection.hasDownStation(targetStation)) {
Section targetSection = line.findSectionWithDownStation(targetStation);
checkAddableByDistance(toAddSection, targetSection);
lineRepository.updateSection(lineId,
new Section(targetSection.id(), lineId, targetSection.upStation(), toAddSection.upStation(), targetSection.subtractDistance(toAddSection)));
}
lineRepository.addSection(lineId, sectionRequest.getUpStationId(), sectionRequest.getDownStationId(), sectionRequest.getDistance());
}
- ์ด๋ ์ํ๊ตฌ๊ฐ ์ฐพ๊ธฐ, ํํ๊ตฌ๊ฐ ์ฐพ๊ธฐ๋ฅผ ์ ๋ตํจํด์ ์ด์ฉํด ๋ฆฌํฉํ ํด๋ฒ๋ ธ์
public class LineService {
private final LineRepository lineRepository;
private final StationDao stationDao;
private final List<FindSectionStrategy> findSectionStrategies;
// ...
- ์ผ๋จ LineService๊ฐ ๊ตฌ๊ฐ์ ์ฐพ๋ ์ ๋ต์ ๊ฐ์ง๊ณ ์์
@Transactional
public void addSection(final Long lineId, final SectionRequest sectionRequest) {
Line line = lineRepository.findById(lineId);
Section toAddSection = sectionRequest.toSection(lineId);
Station targetStation = line.registeredStation(toAddSection);
Section targetSection = line.findSectionWithStation(targetStation, findSectionStrategies);
lineRepository.updateSection(lineId, targetSection.updateToAdd(toAddSection));
lineRepository.addSection(lineId, sectionRequest.getUpStationId(), sectionRequest.getDownStationId(), sectionRequest.getDistance());
}
- ๋์ ๊ตฌ๊ฐ์ ์ฐพ์ ๋ ์ ๋ต๋ค์ ์ฃผ์ ํ๊ณ
public Section findSectionWithStation(Station targetStation, List<FindSectionStrategy> findSectionStrategies) {
return findSectionStrategies.stream()
.map(findSectionStrategy -> findSectionStrategy.findSection(sections, targetStation))
.filter(Optional::isPresent)
.map(Optional::get)
.findAny()
.orElse(EMPTY);
}
- Sections์์ ๋ค์๊ณผ ๊ฐ์ด ํด๋น ๊ตฌ๊ฐ์ ์ฐพ์