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 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 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 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> queryCaptor = ArgumentCaptor.forClass(LambdaQueryWrapper.class); verify(reviewMapper).selectPage(any(Page.class), queryCaptor.capture()); queryCaptor.getValue().getSqlSegment(); assertThat(queryCaptor.getValue().getParamNameValuePairs().values()).contains(42L); } }