Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docker-compose-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ services:
AUCTION_HISTORY_CRON: "${AUCTION_HISTORY_CRON}"
STATISTICS_PREVIOUS_DAY_CRON: "${STATISTICS_PREVIOUS_DAY_CRON:-0 0 * * * *}"

# === Elasticsearch Configuration (Dev 기본 비활성화) ===
ELASTICSEARCH_ENABLED: "false"
ELASTICSEARCH_INDEX_ENABLED: "false"
MANAGEMENT_HEALTH_ELASTICSEARCH_ENABLED: "false"

# === Docker Configuration ===
DOCKER_USERNAME: ${DOCKER_USERNAME}
DOCKER_REPO: ${DOCKER_REPO}
Expand Down Expand Up @@ -128,4 +133,4 @@ volumes:

networks:
app-network:
driver: bridge
driver: bridge
5 changes: 2 additions & 3 deletions docker-compose-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ services:
ELASTICSEARCH_ENABLED: ${ELASTICSEARCH_ENABLED:-true}
ELASTICSEARCH_INDEX_ENABLED: ${ELASTICSEARCH_INDEX_ENABLED:-true}
SPRING_ELASTICSEARCH_URIS: http://elasticsearch:9200
MANAGEMENT_HEALTH_ELASTICSEARCH_ENABLED: "false"

# === JVM Configuration (Local - 경량 개발용) ===
# Heap: 256m~512m, Non-Heap: 256m, Total: ~768m
Expand Down Expand Up @@ -90,12 +91,10 @@ services:
- app-network
- my-network # MySQL 컨테이너와 통신을 위해 추가

# MySQL, Elasticsearch가 준비될 때까지 대기
# MySQL 준비될 때까지 대기 (Elasticsearch는 선택 의존성)
depends_on:
mysql:
condition: service_healthy
elasticsearch:
condition: service_healthy

# === Health Check (Local - 표준) ===
healthcheck:
Expand Down
7 changes: 2 additions & 5 deletions docker-compose-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ services:
labels:
autoheal: "true"

depends_on:
devnogi-elastic-search:
condition: service_healthy

environment:
# === Application Configuration ===
SPRING_PROFILES_ACTIVE: prod
Expand Down Expand Up @@ -51,6 +47,7 @@ services:
ELASTICSEARCH_ENABLED: ${ELASTICSEARCH_ENABLED:-true}
ELASTICSEARCH_INDEX_ENABLED: ${ELASTICSEARCH_INDEX_ENABLED:-true}
SPRING_ELASTICSEARCH_URIS: http://devnogi-elastic-search:9200
MANAGEMENT_HEALTH_ELASTICSEARCH_ENABLED: "false"

# === Docker Configuration ===
DOCKER_USERNAME: ${DOCKER_USERNAME}
Expand Down Expand Up @@ -182,4 +179,4 @@ networks:
driver: bridge
devnogi-network:
external: true
name: infra_devnogi-network # 기존 인프라 네트워크 (MySQL, Redis)
name: infra_devnogi-network # 기존 인프라 네트워크 (MySQL, Redis)
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,13 @@ private List<OrderSpecifier<?>> buildOrderSpecifiers(
case "auctionPricePerUnit" ->
new OrderSpecifier<>(direction, ar.auctionPricePerUnit);
case "itemName" -> new OrderSpecifier<>(direction, ar.itemName);
default -> new OrderSpecifier<>(Order.ASC, ar.dateAuctionExpire);
default -> new OrderSpecifier<>(Order.DESC, ar.dateAuctionExpire);
};

orders.add(orderSpecifier);
}
} else {
orders.add(new OrderSpecifier<>(Order.ASC, ar.dateAuctionExpire));
orders.add(new OrderSpecifier<>(Order.DESC, ar.dateAuctionExpire));
}

return orders;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@
@Schema(description = "실시간 경매장 페이지 요청 파라미터")
public record RealtimePageRequestDto(
@Schema(description = "요청할 페이지 번호 (1부터 시작)", example = "1") @Min(1) Integer page,
@Schema(description = "페이지당 항목 수", example = "20") @Min(1) @Max(100) Integer size,
@Schema(description = "페이지당 항목 수 (10~50)", example = "20") @Min(10) @Max(50) Integer size,
@Schema(
description =
"정렬 필드 (dateAuctionExpire, dateRegister, auctionPricePerUnit, itemName)",
"정렬 필드 (dateAuctionExpire, dateAuctionRegister, auctionPricePerUnit, itemName)",
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

RealtimePageRequestDto의 Schema 설명에 정렬 필드로 dateAuctionRegister가 노출되어 있는데, 실제 정렬 property 및 RealtimeSortField.from() 변환은 dateRegister를 사용합니다. 현재 상태에서는 문서에 나온 값으로 요청하면 기본 정렬로 fallback 되어 사용자가 의도한 정렬이 적용되지 않습니다. 허용되는 query parameter 값 목록을 실제 변환/정렬과 동일하게 맞춰 주세요(또는 alias 지원).

Suggested change
"정렬 필드 (dateAuctionExpire, dateAuctionRegister, auctionPricePerUnit, itemName)",
"정렬 필드 (dateAuctionExpire, dateRegister, auctionPricePerUnit, itemName)",

Copilot uses AI. Check for mistakes.
example = "dateAuctionExpire")
RealtimeSortField sortBy,
@Schema(description = "정렬 방향 (ASC, DESC)", example = "ASC") SortDirection direction) {
@Schema(description = "정렬 방향 (ASC, DESC)", example = "DESC") SortDirection direction) {

private static final int DEFAULT_PAGE = 1;
private static final int DEFAULT_SIZE = 20;
private static final int MIN_SIZE = 10;
private static final int MAX_SIZE = 50;
private static final RealtimeSortField DEFAULT_SORT_BY = RealtimeSortField.DATE_AUCTION_EXPIRE;
private static final SortDirection DEFAULT_DIRECTION = SortDirection.ASC;
private static final SortDirection DEFAULT_DIRECTION = SortDirection.DESC;

public Pageable toPageable() {
int resolvedPage = this.page != null ? this.page - 1 : DEFAULT_PAGE - 1;
int resolvedSize = this.size != null ? this.size : DEFAULT_SIZE;
resolvedSize = Math.max(MIN_SIZE, Math.min(MAX_SIZE, resolvedSize));
RealtimeSortField resolvedSortBy = this.sortBy != null ? this.sortBy : DEFAULT_SORT_BY;
SortDirection resolvedDirection =
this.direction != null ? this.direction : DEFAULT_DIRECTION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@Schema(description = "실시간 경매장 정렬 필드", enumAsRef = true)
public enum RealtimeSortField {
DATE_AUCTION_EXPIRE("dateAuctionExpire", "경매 만료 일시"),
DATE_REGISTER("dateRegister", "등록 일시"),
DATE_AUCTION_REGISTER("dateRegister", "등록 일시"),
AUCTION_PRICE_PER_UNIT("auctionPricePerUnit", "개당 가격"),
Comment on lines 11 to 14
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

RealtimeSortField의 enum 값 이름은 DATE_AUCTION_REGISTER로 바뀌었지만, 실제 query parameter 변환은 from(String fieldName)에서 fieldName(현재 "dateRegister") 기준으로 동작합니다. 그런데 RealtimePageRequestDto의 Schema 설명은 "dateAuctionRegister"를 허용값으로 안내하고 있어, 사용자가 "dateAuctionRegister"로 요청하면 매칭되지 않고 기본값(DATE_AUCTION_EXPIRE)으로 떨어져 의도와 다른 정렬이 됩니다. 문서/변환 로직/정렬 property가 동일한 값을 쓰도록 정렬 파라미터 alias 처리(예: from()에서 dateAuctionRegister도 DATE_AUCTION_REGISTER로 매핑) 또는 Schema 허용값을 실제 fieldName("dateRegister")에 맞춰 수정해 주세요.

Copilot uses AI. Check for mistakes.
ITEM_NAME("itemName", "아이템 이름");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@
@Schema(description = "페이지 요청 파라미터")
public record PageRequestDto(
@Schema(description = "요청할 페이지 번호 (1부터 시작)", example = "1") @Min(1) Integer page,
@Schema(description = "페이지당 항목 수", example = "20") @Min(1) @Max(100) Integer size,
@Schema(description = "페이지당 항목 수 (10~50)", example = "20") @Min(10) @Max(50) Integer size,
@Schema(
description = "정렬 필드 (dateAuctionBuy, auctionPricePerUnit, itemName)",
example = "dateAuctionBuy")
SortField sortBy,
@Schema(description = "정렬 방향 (ASC, DESC)", example = "DESC") SortDirection direction) {
private static final int DEFAULT_PAGE = 1;
private static final int DEFAULT_SIZE = 20;
private static final int MIN_SIZE = 10;
private static final int MAX_SIZE = 50;
private static final SortField DEFAULT_SORT_BY = SortField.DATE_AUCTION_BUY;
private static final SortDirection DEFAULT_DIRECTION = SortDirection.DESC;

public Pageable toPageable() {
int resolvedPage = this.page != null ? this.page - 1 : DEFAULT_PAGE - 1;
int resolvedSize = this.size != null ? this.size : DEFAULT_SIZE;
resolvedSize = Math.max(MIN_SIZE, Math.min(MAX_SIZE, resolvedSize));
SortField resolvedSortBy = this.sortBy != null ? this.sortBy : DEFAULT_SORT_BY;
Comment on lines 28 to 32
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

PageRequestDto.toPageable()에서 size를 10~50으로 강제 clamp 하고 있는데, 레코드 필드에는 @Min(10) @Max(50) 제약도 함께 있습니다. 이 DTO는 AuctionHistoryController에서 @Valid 없이 @ModelAttribute로 사용되고 있어(auctionhistory/interfaces/rest/controller/AuctionHistoryController.java:30), 실제 런타임에서는 검증 에러가 아니라 silent clamp가 적용될 수 있습니다. API가 “검증 실패로 400을 낼지” vs “범위를 자동 보정할지”를 일관되게 정하고, (1) 모든 사용처에서 @Valid를 적용하고 clamp를 제거하거나, (2) 제약 어노테이션을 제거/완화하고 자동 보정 동작을 문서에 명시하는 방향으로 정리해 주세요.

Copilot uses AI. Check for mistakes.
SortDirection resolvedDirection =
this.direction != null ? this.direction : DEFAULT_DIRECTION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import until.the.eternity.auctionhistory.domain.repository.AuctionHistoryRepositoryPort;
import until.the.eternity.common.exception.CustomException;
import until.the.eternity.iteminfo.domain.entity.ItemInfo;
import until.the.eternity.iteminfo.domain.entity.ItemInfoId;
import until.the.eternity.iteminfo.domain.exception.ItemInfoExceptionCode;
import until.the.eternity.iteminfo.domain.repository.ItemInfoRepositoryPort;
import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest;
import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemCategoryResponse;
Expand Down Expand Up @@ -53,7 +51,6 @@ public List<ItemInfoResponse> findBySubCategory(String subCategory) {

public Page<ItemInfoResponse> findAllDetail(
ItemInfoSearchRequest searchRequest, Pageable pageable) {
validateTopCategory(searchRequest);
Page<ItemInfo> itemInfoPage =
itemInfoRepository.searchWithPagination(searchRequest, pageable);
return itemInfoPage.map(ItemInfoResponse::from);
Comment on lines 52 to 56
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

현재 ItemInfoSearchRequest에서 topCategory가 선택으로 변경되면서 null/blank 값이 서비스→레포지토리로 그대로 전달됩니다. 그런데 ItemInfoQueryDslRepository의 where 절은 문자열을 isEmpty()로만 체크하고 있어(즉, 공백 문자열은 조건으로 적용됨), 클라이언트가 실수로 공백을 보내면 “필터 미적용”이 아니라 “topCategory = ' '” 조건으로 조회되어 결과가 비정상적으로 비게 됩니다. 다른 검색 구현들처럼(blank를 미입력으로 간주) 서비스 계층에서 trim/isBlank 기반으로 null 정규화하거나, QueryDSL where 조건을 isBlank 기준으로 바꾸는 쪽으로 동작을 명확히 해주세요.

Copilot uses AI. Check for mistakes.
Expand All @@ -62,7 +59,6 @@ public Page<ItemInfoResponse> findAllDetail(
public List<ItemInfoSummaryResponse> findAllSummary(
ItemInfoSearchRequest searchRequest,
org.springframework.data.domain.Sort.Direction direction) {
validateTopCategory(searchRequest);
// direction을 Pageable로 변환
Pageable pageable =
org.springframework.data.domain.PageRequest.of(
Expand All @@ -73,12 +69,6 @@ public List<ItemInfoSummaryResponse> findAllSummary(
return ItemInfoSummaryResponse.from(itemInfos);
}

private void validateTopCategory(ItemInfoSearchRequest searchRequest) {
if (searchRequest.topCategory() == null || searchRequest.topCategory().isBlank()) {
throw new CustomException(ItemInfoExceptionCode.TOP_CATEGORY_REQUIRED);
}
}

@Transactional
public ItemInfoSyncResponse syncItemInfoFromAuctionHistory() {
log.info("Starting to sync ItemInfo from AuctionHistory");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ public List<ItemInfoResponse> getAllItemInfos() {
summary = "아이템 상세 정보 페이지네이션 조회",
description =
"아이템 정보를 페이지네이션과 함께 조회합니다. "
+ "topCategory는 필수 파라미터이며, name, subCategory로 추가 필터링 가능합니다. "
+ "name 컬럼 기준으로 정렬됩니다.")
+ "topCategory는 선택 파라미터이며, name, subCategory로 추가 필터링 가능합니다. "
+ "정렬 기준은 item_name(ASC/DESC)이고 기본값은 ASC입니다. "
+ "page는 1 이상, size는 10~50 사이 값만 허용됩니다.")
@GetMapping("/detail")
public ResponseEntity<ApiResponse<Page<ItemInfoResponse>>> getItemInfosDetail(
@Valid @ModelAttribute ItemInfoPageRequestDto pageRequest,
Expand All @@ -60,8 +61,8 @@ public ResponseEntity<ApiResponse<Page<ItemInfoResponse>>> getItemInfosDetail(
summary = "아이템 요약 정보 조회",
description =
"아이템의 이름, 상위 카테고리, 하위 카테고리만 조회합니다. "
+ "topCategory는 필수 파라미터이며, name, subCategory로 추가 필터링 가능합니다. "
+ "name 컬럼 기준으로 정렬됩니다.")
+ "topCategory는 선택 파라미터이며, name, subCategory로 추가 필터링 가능합니다. "
+ "정렬 기준은 item_name이며 direction 파라미터로 ASC/DESC를 지정합니다.")
@GetMapping("/summary")
public ResponseEntity<ApiResponse<List<ItemInfoSummaryResponse>>> getItemInfosSummary(
@Parameter(description = "정렬 방향 (ASC, DESC)", example = "ASC")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@
@Schema(description = "아이템 정보 페이지 요청 파라미터")
public record ItemInfoPageRequestDto(
@Schema(description = "요청할 페이지 번호 (1부터 시작)", example = "1") @Min(1) Integer page,
@Schema(description = "페이지당 항목 수", example = "20") @Min(1) @Max(50) Integer size,
@Schema(description = "정렬 방향 (ASC, DESC)", example = "ASC") SortDirection direction) {
@Schema(description = "페이지당 항목 수 (10~50)", example = "20") @Min(10) @Max(50) Integer size,
@Schema(description = "정렬 방향 (item_name 기준 ASC, DESC)", example = "ASC")
SortDirection direction) {
private static final int DEFAULT_PAGE = 1;
private static final int DEFAULT_SIZE = 20;
private static final int MIN_SIZE = 10;
private static final int MAX_SIZE = 50;
private static final SortDirection DEFAULT_DIRECTION = SortDirection.ASC;
private static final String SORT_FIELD = "id.name";

public Pageable toPageable() {
int resolvedPage = this.page != null ? this.page - 1 : DEFAULT_PAGE - 1;
int resolvedSize = this.size != null ? this.size : DEFAULT_SIZE;
resolvedSize = Math.max(MIN_SIZE, Math.min(MAX_SIZE, resolvedSize));
SortDirection resolvedDirection =
this.direction != null ? this.direction : DEFAULT_DIRECTION;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package until.the.eternity.iteminfo.interfaces.rest.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;

@Schema(description = "아이템 정보 검색 요청 파라미터")
public record ItemInfoSearchRequest(
@Schema(description = "아이템 이름", example = "나뭇가지") String name,
@Schema(description = "하위 카테고리", example = "한손검") String subCategory,
@Schema(description = "상위 카테고리 (필수)", example = "무기", required = true)
@NotBlank(message = "상위 카테고리(topCategory)는 필수 파라미터입니다.")
String topCategory) {}
@Schema(description = "상위 카테고리 (선택)", example = "무기") String topCategory) {}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.*;
import until.the.eternity.auctionhistory.domain.repository.AuctionHistoryRepositoryPort;
import until.the.eternity.common.exception.CustomException;
import until.the.eternity.iteminfo.domain.entity.ItemInfo;
import until.the.eternity.iteminfo.domain.entity.ItemInfoId;
import until.the.eternity.iteminfo.domain.exception.ItemInfoExceptionCode;
import until.the.eternity.iteminfo.domain.repository.ItemInfoRepositoryPort;
import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest;
import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemCategoryResponse;
Expand All @@ -23,7 +21,6 @@
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -118,29 +115,37 @@ void findAll_should_return_empty_list_when_no_data() {
}

@Test
@DisplayName("상세 정보 조회 시 topCategory가 없으면 예외가 발생한다")
void findAllDetail_should_throw_exception_when_topCategory_is_null() {
@DisplayName("상세 정보 조회 시 topCategory가 없어도 조회된다")
void findAllDetail_should_allow_null_topCategory() {
// given
ItemInfoSearchRequest searchRequest = new ItemInfoSearchRequest(null, null, null);
Pageable pageable = PageRequest.of(0, 20);
Page<ItemInfo> emptyPage = new PageImpl<>(List.of(), pageable, 0);
when(itemInfoRepository.searchWithPagination(searchRequest, pageable)).thenReturn(emptyPage);

// when
Page<ItemInfoResponse> result = itemInfoService.findAllDetail(searchRequest, pageable);

// when & then
assertThatThrownBy(() -> itemInfoService.findAllDetail(searchRequest, pageable))
.isInstanceOf(CustomException.class)
.hasMessage(ItemInfoExceptionCode.TOP_CATEGORY_REQUIRED.getMessage());
// then
assertThat(result.getContent()).isEmpty();
verify(itemInfoRepository).searchWithPagination(searchRequest, pageable);
}

@Test
@DisplayName("상세 정보 조회 시 topCategory가 빈 문자열이면 예외가 발생한다")
void findAllDetail_should_throw_exception_when_topCategory_is_blank() {
@DisplayName("상세 정보 조회 시 topCategory가 공백이어도 조회된다")
void findAllDetail_should_allow_blank_topCategory() {
// given
ItemInfoSearchRequest searchRequest = new ItemInfoSearchRequest(null, null, "");
Pageable pageable = PageRequest.of(0, 20);
Page<ItemInfo> emptyPage = new PageImpl<>(List.of(), pageable, 0);
when(itemInfoRepository.searchWithPagination(searchRequest, pageable)).thenReturn(emptyPage);

// when
Page<ItemInfoResponse> result = itemInfoService.findAllDetail(searchRequest, pageable);

// when & then
assertThatThrownBy(() -> itemInfoService.findAllDetail(searchRequest, pageable))
.isInstanceOf(CustomException.class)
.hasMessage(ItemInfoExceptionCode.TOP_CATEGORY_REQUIRED.getMessage());
// then
assertThat(result.getContent()).isEmpty();
verify(itemInfoRepository).searchWithPagination(searchRequest, pageable);
}

@Test
Expand Down Expand Up @@ -191,15 +196,19 @@ void findAllDetail_should_return_filtered_items_with_all_conditions() {
}

@Test
@DisplayName("요약 정보 조회 시 topCategory가 없으면 예외가 발생한다")
void findAllSummary_should_throw_exception_when_topCategory_is_null() {
@DisplayName("요약 정보 조회 시 topCategory 없이도 조회된다")
void findAllSummary_should_allow_null_topCategory() {
// given
ItemInfoSearchRequest searchRequest = new ItemInfoSearchRequest(null, null, null);
when(itemInfoRepository.search(eq(searchRequest), any(Pageable.class))).thenReturn(List.of());

// when & then
assertThatThrownBy(() -> itemInfoService.findAllSummary(searchRequest, Sort.Direction.ASC))
.isInstanceOf(CustomException.class)
.hasMessage(ItemInfoExceptionCode.TOP_CATEGORY_REQUIRED.getMessage());
// when
List<ItemInfoSummaryResponse> result =
itemInfoService.findAllSummary(searchRequest, Sort.Direction.ASC);

// then
assertThat(result).isEmpty();
verify(itemInfoRepository).search(eq(searchRequest), any(Pageable.class));
}

@Test
Expand Down Expand Up @@ -319,15 +328,19 @@ void findBySubCategory_should_return_empty_list_when_no_results() {
}

@Test
@DisplayName("요약 정보 조회 시 topCategory가 빈 문자열이면 예외가 발생한다")
void findAllSummary_should_throw_exception_when_topCategory_is_blank() {
@DisplayName("요약 정보 조회 시 topCategory가 공백이어도 조회된다")
void findAllSummary_should_allow_blank_topCategory() {
// given
ItemInfoSearchRequest searchRequest = new ItemInfoSearchRequest(null, null, "");
when(itemInfoRepository.search(eq(searchRequest), any(Pageable.class))).thenReturn(List.of());

// when & then
assertThatThrownBy(() -> itemInfoService.findAllSummary(searchRequest, Sort.Direction.ASC))
.isInstanceOf(CustomException.class)
.hasMessage(ItemInfoExceptionCode.TOP_CATEGORY_REQUIRED.getMessage());
// when
List<ItemInfoSummaryResponse> result =
itemInfoService.findAllSummary(searchRequest, Sort.Direction.ASC);

// then
assertThat(result).isEmpty();
verify(itemInfoRepository).search(eq(searchRequest), any(Pageable.class));
}

@Test
Expand Down