Skip to content

Commit aee2827

Browse files
authored
[Feat] 가게 상세 정보 조회 API 구현
2 parents e6c7fe8 + 8fdfe16 commit aee2827

File tree

7 files changed

+170
-5
lines changed

7 files changed

+170
-5
lines changed

src/main/java/eatda/controller/store/StoreController.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.RequiredArgsConstructor;
88
import org.springframework.http.ResponseEntity;
99
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.PathVariable;
1011
import org.springframework.web.bind.annotation.RequestParam;
1112
import org.springframework.web.bind.annotation.RestController;
1213

@@ -21,6 +22,12 @@ public ResponseEntity<StoresResponse> getStores(@RequestParam @Min(1) @Max(50) i
2122
return ResponseEntity.ok(storeService.getStores(size));
2223
}
2324

25+
@GetMapping("/api/shops/{storeId}")
26+
public ResponseEntity<StoreResponse> getStore(@PathVariable long storeId) {
27+
StoreResponse response = storeService.getStore(storeId);
28+
return ResponseEntity.ok(response);
29+
}
30+
2431
@GetMapping("/api/shop/search")
2532
public ResponseEntity<StoreSearchResponses> searchStore(@RequestParam String query, LoginMember member) {
2633
StoreSearchResponses response = storeService.searchStores(query);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package eatda.controller.store;
2+
3+
import eatda.domain.store.Store;
4+
5+
public record StoreResponse(
6+
long id,
7+
String kakaoId,
8+
String name,
9+
String district,
10+
String neighborhood,
11+
String category,
12+
String placeUrl
13+
) {
14+
15+
public StoreResponse(Store store) {
16+
this(
17+
store.getId(),
18+
store.getKakaoId(),
19+
store.getName(),
20+
store.getAddressDistrict(),
21+
store.getAddressNeighborhood(),
22+
store.getCategory().getCategoryName(),
23+
store.getPlaceUrl()
24+
);
25+
}
26+
}

src/main/java/eatda/repository/store/StoreRepository.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package eatda.repository.store;
22

33
import eatda.domain.store.Store;
4+
import eatda.exception.BusinessErrorCode;
5+
import eatda.exception.BusinessException;
46
import java.util.List;
57
import java.util.Optional;
68
import org.springframework.data.domain.Pageable;
7-
import org.springframework.data.repository.Repository;
9+
import org.springframework.data.jpa.repository.JpaRepository;
810

9-
public interface StoreRepository extends Repository<Store, Long> {
11+
public interface StoreRepository extends JpaRepository<Store, Long> {
1012

11-
Store save(Store store);
13+
@Override
14+
default Store getById(Long id) {
15+
return findById(id)
16+
.orElseThrow(() -> new BusinessException(BusinessErrorCode.STORE_NOT_FOUND));
17+
}
1218

1319
Optional<Store> findByKakaoId(String kakaoId);
1420

src/main/java/eatda/service/store/StoreService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import eatda.client.map.MapClient;
77
import eatda.client.map.StoreSearchResult;
88
import eatda.controller.store.StorePreviewResponse;
9+
import eatda.controller.store.StoreResponse;
910
import eatda.controller.store.StoreSearchResponses;
1011
import eatda.controller.store.StoresResponse;
1112
import eatda.domain.store.Store;
@@ -28,6 +29,11 @@ public class StoreService {
2829
private final CheerRepository cheerRepository;
2930
private final ImageStorage imageStorage;
3031

32+
public StoreResponse getStore(long storeId) {
33+
Store store = storeRepository.getById(storeId);
34+
return new StoreResponse(store);
35+
}
36+
3137
// TODO : N+1 문제 해결
3238
public StoresResponse getStores(int size) {
3339
return storeRepository.findAllByOrderByCreatedAtDesc(Pageable.ofSize(size))

src/test/java/eatda/controller/store/StoreControllerTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@
1212

1313
class StoreControllerTest extends BaseControllerTest {
1414

15+
@Nested
16+
class GetStore {
17+
18+
@Test
19+
void 음식점_정보를_조회한다() {
20+
Member member = memberGenerator.generate("111");
21+
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
22+
cheerGenerator.generateCommon(member, store, "image-key");
23+
24+
StoreResponse response = given()
25+
.pathParam("storeId", store.getId())
26+
.when()
27+
.get("/api/shops/{storeId}")
28+
.then()
29+
.statusCode(200)
30+
.extract().as(StoreResponse.class);
31+
32+
assertAll(
33+
() -> assertThat(response.id()).isEqualTo(store.getId()),
34+
() -> assertThat(response.name()).isEqualTo(store.getName()),
35+
() -> assertThat(response.district()).isEqualTo("강남구"),
36+
() -> assertThat(response.neighborhood()).isEqualTo("대치동")
37+
);
38+
}
39+
}
40+
1541
@Nested
1642
class GetStores {
1743

src/test/java/eatda/document/store/StoreDocumentTest.java

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33

44
import static org.mockito.ArgumentMatchers.anyInt;
5+
import static org.mockito.ArgumentMatchers.anyLong;
56
import static org.mockito.ArgumentMatchers.anyString;
67
import static org.mockito.Mockito.doReturn;
78
import static org.mockito.Mockito.doThrow;
@@ -13,6 +14,7 @@
1314
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
1415

1516
import eatda.controller.store.StorePreviewResponse;
17+
import eatda.controller.store.StoreResponse;
1618
import eatda.controller.store.StoreSearchResponse;
1719
import eatda.controller.store.StoreSearchResponses;
1820
import eatda.controller.store.StoresResponse;
@@ -32,6 +34,64 @@
3234

3335
public class StoreDocumentTest extends BaseDocumentTest {
3436

37+
@Nested
38+
class GetStore {
39+
RestDocsRequest requestDocument = request()
40+
.tag(Tag.STORE_API)
41+
.summary("음식점 정보 조회")
42+
.pathParameter(
43+
parameterWithName("storeId").description("음식점 ID")
44+
);
45+
46+
RestDocsResponse responseDocument = response()
47+
.responseBodyField(
48+
fieldWithPath("id").type(NUMBER).description("음식점 ID"),
49+
fieldWithPath("kakaoId").type(STRING).description("카카오 음식점 ID"),
50+
fieldWithPath("name").type(STRING).description("음식점 이름"),
51+
fieldWithPath("district").type(STRING).description("음식점 주소 (구)"),
52+
fieldWithPath("neighborhood").type(STRING).description("음식점 주소 (동)"),
53+
fieldWithPath("category").type(STRING).description("음식점 카테고리"),
54+
fieldWithPath("placeUrl").type(STRING).description("음식점 카카오맵 URL")
55+
);
56+
57+
@Test
58+
void 음식점_정보를_조회() {
59+
StoreResponse response = new StoreResponse(1L, "17163273", "농민백암순대", "강남구", "대치동",
60+
"한식", "https://place.map.kakao.com/17163273");
61+
doReturn(response).when(storeService).getStore(anyLong());
62+
63+
long storeId = 1L;
64+
var document = document("store/get-store", 200)
65+
.request(requestDocument)
66+
.response(responseDocument)
67+
.build();
68+
69+
given(document)
70+
.contentType(ContentType.JSON)
71+
.pathParam("storeId", storeId)
72+
.when().get("/api/shops/{storeId}")
73+
.then().statusCode(200);
74+
}
75+
76+
@EnumSource(value = BusinessErrorCode.class, names = {"STORE_NOT_FOUND"})
77+
@ParameterizedTest
78+
void 음식점_정보_조회_실패(BusinessErrorCode errorCode) {
79+
doThrow(new BusinessException(errorCode)).when(storeService).getStore(anyLong());
80+
81+
long storeId = 1L;
82+
var document = document("store/get-store", errorCode)
83+
.request(requestDocument)
84+
.response(ERROR_RESPONSE)
85+
.build();
86+
87+
given(document)
88+
.contentType(ContentType.JSON)
89+
.pathParam("storeId", storeId)
90+
.when().get("/api/shops/{storeId}")
91+
.then().statusCode(errorCode.getStatus().value());
92+
}
93+
}
94+
3595
@Nested
3696
class GetStores {
3797

@@ -62,7 +122,7 @@ class GetStores {
62122
doReturn(response).when(storeService).getStores(anyInt());
63123

64124
int size = 2;
65-
var document = document("store/get", 200)
125+
var document = document("store/get-stores", 200)
66126
.request(requestDocument)
67127
.response(responseDocument)
68128
.build();
@@ -80,7 +140,7 @@ class GetStores {
80140
doThrow(new BusinessException(errorCode)).when(storeService).getStores(anyInt());
81141

82142
int size = 2;
83-
var document = document("store/get", errorCode)
143+
var document = document("store/get-stores", errorCode)
84144
.request(requestDocument)
85145
.response(ERROR_RESPONSE)
86146
.build();

src/test/java/eatda/service/store/StoreServiceTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.junit.jupiter.api.Assertions.assertAll;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
56
import static org.mockito.ArgumentMatchers.anyString;
67
import static org.mockito.Mockito.doReturn;
78

89
import eatda.client.map.StoreSearchResult;
10+
import eatda.controller.store.StoreResponse;
911
import eatda.domain.member.Member;
1012
import eatda.domain.store.Store;
13+
import eatda.exception.BusinessErrorCode;
14+
import eatda.exception.BusinessException;
1115
import eatda.service.BaseServiceTest;
1216
import java.util.List;
1317
import org.junit.jupiter.api.Nested;
@@ -19,6 +23,36 @@ class StoreServiceTest extends BaseServiceTest {
1923
@Autowired
2024
private StoreService storeService;
2125

26+
@Nested
27+
class GetStore {
28+
29+
@Test
30+
void 음식점_정보를_조회한다() {
31+
Member member = memberGenerator.generate("111");
32+
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
33+
cheerGenerator.generateCommon(member, store, "image-key");
34+
35+
StoreResponse response = storeService.getStore(store.getId());
36+
37+
assertAll(
38+
() -> assertThat(response.id()).isEqualTo(store.getId()),
39+
() -> assertThat(response.name()).isEqualTo(store.getName()),
40+
() -> assertThat(response.district()).isEqualTo("강남구"),
41+
() -> assertThat(response.neighborhood()).isEqualTo("대치동")
42+
);
43+
}
44+
45+
@Test
46+
void 해당_음식점이_없을_경우_예외를_던진다() {
47+
long nonExistentStoreId = 999L;
48+
49+
BusinessException exception = assertThrows(BusinessException.class,
50+
() -> storeService.getStore(nonExistentStoreId));
51+
52+
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.STORE_NOT_FOUND);
53+
}
54+
}
55+
2256
@Nested
2357
class GetStores {
2458

0 commit comments

Comments
 (0)