package com.tcm.training.admin.member.service; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.tcm.training.admin.member.dto.MemberIntroModuleSaveRequest; import com.tcm.training.admin.member.dto.MemberIntroSettingsSaveRequest; import com.tcm.training.admin.member.dto.MemberPriceSettingsSaveRequest; import com.tcm.training.admin.member.entity.MemberIntroConfig; import com.tcm.training.admin.member.entity.MemberIntroItem; import com.tcm.training.admin.member.entity.MemberPriceConfig; import com.tcm.training.admin.member.mapper.MemberIntroConfigMapper; import com.tcm.training.admin.member.mapper.MemberIntroItemMapper; import com.tcm.training.admin.member.mapper.MemberPriceConfigMapper; import com.tcm.training.admin.member.vo.MemberIntroSettingsVO; import com.tcm.training.admin.member.vo.MemberPriceSettingsVO; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.ExtendWith; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.math.BigDecimal; import java.util.Arrays; import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MemberSettingsAppServiceTest { @BeforeAll static void initLambdaCache() { MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(), ""); TableInfoHelper.initTableInfo(assistant, MemberPriceConfig.class); TableInfoHelper.initTableInfo(assistant, MemberIntroItem.class); } @Mock private MemberPriceConfigMapper memberPriceConfigMapper; @Mock private MemberIntroConfigMapper memberIntroConfigMapper; @Mock private MemberIntroItemMapper memberIntroItemMapper; @InjectMocks private MemberSettingsAppService memberSettingsAppService; @Captor private ArgumentCaptor priceConfigCaptor; @Captor private ArgumentCaptor introConfigCaptor; @Captor private ArgumentCaptor introItemCaptor; @Test void currentPriceShouldReturnNullWhenConfigMissing() { when(memberPriceConfigMapper.selectOne(any())).thenReturn(null); MemberPriceSettingsVO result = memberSettingsAppService.currentPrice(); assertNull(result); } @Test void saveCurrentPriceShouldUpdateLatestConfig() { MemberPriceConfig existing = new MemberPriceConfig(); existing.setId(5L); when(memberPriceConfigMapper.selectOne(any())).thenReturn(existing); MemberPriceSettingsSaveRequest request = new MemberPriceSettingsSaveRequest(); request.setMonthCardPrice(new BigDecimal("69.00")); request.setMonthCardDays(30); request.setMonthCardEnabled(Boolean.TRUE); request.setQuarterCardPrice(new BigDecimal("199.00")); request.setQuarterCardDays(90); request.setQuarterCardEnabled(Boolean.FALSE); MemberPriceSettingsVO result = memberSettingsAppService.saveCurrentPrice(request); verify(memberPriceConfigMapper).updateById(priceConfigCaptor.capture()); assertEquals(Long.valueOf(5L), priceConfigCaptor.getValue().getId()); assertEquals(new BigDecimal("69.00"), result.getMonthCardPrice()); assertEquals(Boolean.FALSE, result.getQuarterCardEnabled()); verify(memberPriceConfigMapper, never()).insert(any()); } @Test void saveCurrentPriceShouldInsertCardConfig() { when(memberPriceConfigMapper.selectOne(any())).thenReturn(null); MemberPriceSettingsSaveRequest request = new MemberPriceSettingsSaveRequest(); request.setMonthCardPrice(new BigDecimal("69.00")); request.setMonthCardDays(30); request.setMonthCardEnabled(Boolean.TRUE); request.setQuarterCardPrice(new BigDecimal("199.00")); request.setQuarterCardDays(90); request.setQuarterCardEnabled(Boolean.TRUE); MemberPriceSettingsVO result = memberSettingsAppService.saveCurrentPrice(request); verify(memberPriceConfigMapper).insert(priceConfigCaptor.capture()); MemberPriceConfig savedEntity = priceConfigCaptor.getValue(); assertEquals(new BigDecimal("69.00"), savedEntity.getMonthCardPrice()); assertEquals(Integer.valueOf(1), savedEntity.getMonthCardEnabled()); assertEquals(new BigDecimal("69.00"), result.getMonthCardPrice()); assertEquals(new BigDecimal("199.00"), result.getQuarterCardPrice()); } @Test void saveCurrentPriceShouldRejectInvalidMonthCardPrice() { MemberPriceSettingsSaveRequest request = new MemberPriceSettingsSaveRequest(); request.setMonthCardPrice(BigDecimal.ZERO); request.setMonthCardDays(30); request.setMonthCardEnabled(Boolean.TRUE); request.setQuarterCardPrice(new BigDecimal("199.00")); request.setQuarterCardDays(90); request.setQuarterCardEnabled(Boolean.TRUE); IllegalArgumentException error = assertThrows( IllegalArgumentException.class, () -> memberSettingsAppService.saveCurrentPrice(request) ); assertEquals("月卡会员价格必须大于0", error.getMessage()); verify(memberPriceConfigMapper, never()).insert(any()); verify(memberPriceConfigMapper, never()).updateById(any()); } @Test void saveCurrentPriceShouldRejectMissingQuarterEnabled() { MemberPriceSettingsSaveRequest request = new MemberPriceSettingsSaveRequest(); request.setMonthCardPrice(new BigDecimal("69.00")); request.setMonthCardDays(30); request.setMonthCardEnabled(Boolean.TRUE); request.setQuarterCardPrice(new BigDecimal("199.00")); request.setQuarterCardDays(90); request.setQuarterCardEnabled(null); IllegalArgumentException error = assertThrows( IllegalArgumentException.class, () -> memberSettingsAppService.saveCurrentPrice(request) ); assertEquals("请选择季卡是否启用", error.getMessage()); verify(memberPriceConfigMapper, never()).insert(any()); verify(memberPriceConfigMapper, never()).updateById(any()); } @Test void currentIntroShouldMapModules() { MemberIntroConfig config = new MemberIntroConfig(); config.setId(1L); config.setModuleCount(2); config.setDescription("会员权益说明"); when(memberIntroConfigMapper.selectOne(any())).thenReturn(config); MemberIntroItem first = new MemberIntroItem(); first.setId(11L); first.setConfigId(1L); first.setIconUrl("https://img.test/one.png"); first.setName("折扣"); first.setSort(1); MemberIntroItem second = new MemberIntroItem(); second.setId(12L); second.setConfigId(1L); second.setIconUrl("https://img.test/two.png"); second.setName("专区"); second.setSort(2); when(memberIntroItemMapper.selectList(any())).thenReturn(Arrays.asList(first, second)); MemberIntroSettingsVO result = memberSettingsAppService.currentIntro(); assertEquals(2, result.getModuleCount().intValue()); assertEquals("会员权益说明", result.getDescription()); assertEquals(2, result.getBenefits().size()); assertEquals("https://img.test/one.png", result.getBenefits().get(0).getIconUrl()); assertEquals("专区", result.getBenefits().get(1).getName()); } @Test void saveCurrentIntroShouldRejectEmptyBenefitName() { MemberIntroSettingsSaveRequest request = new MemberIntroSettingsSaveRequest(); MemberIntroModuleSaveRequest module = new MemberIntroModuleSaveRequest(); module.setIconUrl("https://img.test/one.png"); module.setName(" "); request.setBenefits(Collections.singletonList(module)); IllegalArgumentException error = assertThrows( IllegalArgumentException.class, () -> memberSettingsAppService.saveCurrentIntro(request) ); assertEquals("请输入第1个权益名称", error.getMessage()); verify(memberIntroConfigMapper, never()).insert(any()); } @Test void saveCurrentIntroShouldSoftDeleteOldItemsAndInsertNewOnes() { MemberIntroConfig config = new MemberIntroConfig(); config.setId(8L); config.setModuleCount(1); when(memberIntroConfigMapper.selectOne(any())).thenReturn(config); MemberIntroModuleSaveRequest first = new MemberIntroModuleSaveRequest(); first.setIconUrl("https://img.test/one.png"); first.setName("折扣"); MemberIntroModuleSaveRequest second = new MemberIntroModuleSaveRequest(); second.setIconUrl("https://img.test/two.png"); second.setName("专区"); MemberIntroSettingsSaveRequest request = new MemberIntroSettingsSaveRequest(); request.setBenefits(Arrays.asList(first, second)); request.setDescription("新的权益说明"); MemberIntroSettingsVO result = memberSettingsAppService.saveCurrentIntro(request); verify(memberIntroConfigMapper).updateById(introConfigCaptor.capture()); assertEquals(2, introConfigCaptor.getValue().getModuleCount().intValue()); assertEquals("新的权益说明", introConfigCaptor.getValue().getDescription()); verify(memberIntroItemMapper).update(any(), any(LambdaUpdateWrapper.class)); verify(memberIntroItemMapper, times(2)).insert(introItemCaptor.capture()); assertEquals(2, introItemCaptor.getAllValues().size()); assertEquals(Integer.valueOf(1), introItemCaptor.getAllValues().get(0).getSort()); assertEquals(Integer.valueOf(2), introItemCaptor.getAllValues().get(1).getSort()); assertEquals(2, result.getBenefits().size()); assertEquals("新的权益说明", result.getDescription()); assertTrue(result.getBenefits().stream().allMatch(item -> item.getIconUrl().startsWith("https://img.test/"))); } }