package com.tourguide.modules.review.service;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import com.tourguide.modules.order.mapper.TourOrderMapper;
|
import com.tourguide.modules.order.domain.OrderStatus;
|
import com.tourguide.modules.order.entity.TourOrder;
|
import com.tourguide.modules.review.dto.OrderReviewCreateRequest;
|
import com.tourguide.modules.review.dto.GuideRatingItemResponse;
|
import com.tourguide.modules.review.dto.GuideRatingResponse;
|
import com.tourguide.modules.review.entity.OrderReview;
|
import com.tourguide.modules.review.mapper.OrderReviewMapper;
|
import com.tourguide.modules.review.dto.OrderReviewResponse;
|
import com.tourguide.modules.system.service.GuideNotificationService;
|
import com.tourguide.modules.user.entity.GuideUser;
|
import com.tourguide.modules.user.mapper.GuideUserMapper;
|
import com.tourguide.modules.user.service.GuideAutoDisableService;
|
import org.junit.jupiter.api.Test;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.util.Collections;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
import org.mockito.ArgumentCaptor;
|
|
class OrderReviewServiceTest {
|
private static boolean tableInfoInitialized;
|
|
private static void initializeTableInfo() {
|
if (!tableInfoInitialized) {
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), OrderReview.class);
|
tableInfoInitialized = true;
|
}
|
}
|
|
@Test
|
void guideRatingsShouldReturnGuideScoreAndVisibleReviewPage() {
|
OrderReviewMapper reviewMapper = mock(OrderReviewMapper.class);
|
TourOrderMapper orderMapper = mock(TourOrderMapper.class);
|
GuideUserMapper guideUserMapper = mock(GuideUserMapper.class);
|
OrderReviewService reviewService = new OrderReviewService(
|
reviewMapper, orderMapper, guideUserMapper, mock(GuideAutoDisableService.class));
|
|
GuideUser guide = new GuideUser();
|
guide.setId(12L);
|
guide.setStatus(1);
|
guide.setRating(new BigDecimal("4.80"));
|
when(guideUserMapper.selectById(12L)).thenReturn(guide);
|
|
OrderReview review = new OrderReview();
|
review.setId(21L);
|
review.setGuideId(12L);
|
review.setScore(new BigDecimal("5.0"));
|
review.setContent("讲解专业");
|
review.setImageUrls("[\"/uploads/review-images/example.jpg\"]");
|
review.setReviewedAt(LocalDateTime.of(2026, 7, 29, 10, 30));
|
review.setStatus(1);
|
|
when(reviewMapper.selectPage(any(Page.class), any())).thenAnswer(invocation -> {
|
Page<OrderReview> requestedPage = invocation.getArgument(0);
|
requestedPage.setRecords(Collections.singletonList(review));
|
requestedPage.setTotal(1);
|
return requestedPage;
|
});
|
|
GuideRatingResponse response = reviewService.guideRatings(
|
12L, LocalDate.of(2026, 7, 29), 0, 200);
|
|
assertThat(response.getScore()).isEqualByComparingTo("4.80");
|
assertThat(response.getPageNum()).isEqualTo(1);
|
assertThat(response.getPageSize()).isEqualTo(100);
|
assertThat(response.getTotal()).isEqualTo(1);
|
assertThat(response.getRows()).hasSize(1);
|
assertThat(response.getRows().get(0).getDateText()).isEqualTo("2026年7月29日");
|
assertThat(response.getRows().get(0).getComment()).isEqualTo("讲解专业");
|
assertThat(response.getRows().get(0).getImages())
|
.containsExactly("/uploads/review-images/example.jpg");
|
}
|
|
@Test
|
void reviewResponsesShouldParseLegacyImageFormats() {
|
OrderReview review = new OrderReview();
|
review.setImageUrls("/uploads/review-images/one.jpg,/uploads/review-images/two.jpg");
|
|
assertThat(new GuideRatingItemResponse(review).getImages())
|
.containsExactly("/uploads/review-images/one.jpg", "/uploads/review-images/two.jpg");
|
assertThat(new OrderReviewResponse(review).getImages())
|
.containsExactly("/uploads/review-images/one.jpg", "/uploads/review-images/two.jpg");
|
}
|
|
@Test
|
void reviewRequestShouldAcceptImageUrlAliases() throws Exception {
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
OrderReviewCreateRequest request = objectMapper.readValue(
|
"{\"orderId\":99,\"score\":5,\"image_urls\":[\"/uploads/review-images/example.jpg\"]}",
|
OrderReviewCreateRequest.class);
|
|
assertThat(request.getImages()).containsExactly("/uploads/review-images/example.jpg");
|
}
|
|
@Test
|
void createShouldNotifyGuideAfterReviewIsSaved() {
|
OrderReviewMapper reviewMapper = mock(OrderReviewMapper.class);
|
TourOrderMapper orderMapper = mock(TourOrderMapper.class);
|
GuideUserMapper guideUserMapper = mock(GuideUserMapper.class);
|
GuideNotificationService notificationService = mock(GuideNotificationService.class);
|
OrderReviewService reviewService = new OrderReviewService(
|
reviewMapper, orderMapper, guideUserMapper, mock(GuideAutoDisableService.class),
|
new ObjectMapper(), notificationService);
|
|
TourOrder order = new TourOrder();
|
order.setId(99L);
|
order.setOrderNo("ORDER-99");
|
order.setVisitorId(7L);
|
order.setGuideId(8L);
|
order.setStatus(OrderStatus.COMPLETED.getCode());
|
when(orderMapper.selectById(99L)).thenReturn(order);
|
when(reviewMapper.countByOrderId(99L)).thenReturn(0L);
|
|
GuideUser guide = new GuideUser();
|
guide.setId(8L);
|
guide.setStatus(1);
|
when(guideUserMapper.selectById(8L)).thenReturn(guide);
|
when(reviewMapper.selectAverageScore(8L)).thenReturn(new BigDecimal("5.00"));
|
|
OrderReviewCreateRequest request = new OrderReviewCreateRequest();
|
request.setOrderId(99L);
|
request.setScore(new BigDecimal("5.00"));
|
request.setContent("服务很好");
|
request.setImages(Collections.singletonList("/uploads/review-images/example.jpg"));
|
|
reviewService.create(7L, request);
|
|
ArgumentCaptor<OrderReview> reviewCaptor = ArgumentCaptor.forClass(OrderReview.class);
|
verify(reviewMapper).insert(reviewCaptor.capture());
|
assertThat(reviewCaptor.getValue().getImageUrls())
|
.isEqualTo("[\"/uploads/review-images/example.jpg\"]");
|
verify(notificationService).notifyOrderReviewed(order);
|
}
|
|
@Test
|
void pageShouldFilterReviewsByVisitorId() {
|
initializeTableInfo();
|
OrderReviewMapper reviewMapper = mock(OrderReviewMapper.class);
|
OrderReviewService reviewService = new OrderReviewService(
|
reviewMapper, mock(TourOrderMapper.class), mock(GuideUserMapper.class),
|
mock(GuideAutoDisableService.class));
|
when(reviewMapper.selectPage(any(Page.class), any())).thenAnswer(invocation -> invocation.getArgument(0));
|
|
reviewService.page(1, 10, null, 42L, null, null, null, null, null);
|
|
ArgumentCaptor<LambdaQueryWrapper<OrderReview>> queryCaptor = ArgumentCaptor.forClass(LambdaQueryWrapper.class);
|
verify(reviewMapper).selectPage(any(Page.class), queryCaptor.capture());
|
queryCaptor.getValue().getSqlSegment();
|
assertThat(queryCaptor.getValue().getParamNameValuePairs().values()).contains(42L);
|
}
|
}
|