|
@@ -1,34 +1,56 @@
|
|
|
package cn.iocoder.yudao.module.system.service.tenant;
|
|
|
|
|
|
+import cn.hutool.core.util.ReflectUtil;
|
|
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
|
|
|
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
|
|
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
|
|
|
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
|
|
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
|
|
+import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
|
|
|
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
|
|
|
+import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
|
|
|
+import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
|
|
|
import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
|
|
|
import cn.iocoder.yudao.module.system.service.permission.MenuService;
|
|
|
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
|
|
import cn.iocoder.yudao.module.system.service.permission.RoleService;
|
|
|
+import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
|
|
|
+import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
|
|
|
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
|
|
import cn.iocoder.yudao.module.system.test.BaseDbUnitTest;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
|
import org.springframework.context.annotation.Import;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.time.Duration;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
|
|
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
|
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
|
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
|
|
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
|
|
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS;
|
|
|
+import static cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO.PACKAGE_ID_SYSTEM;
|
|
|
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
|
|
+import static java.util.Arrays.asList;
|
|
|
+import static java.util.Collections.singleton;
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
+import static org.mockito.ArgumentMatchers.*;
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
|
|
|
/**
|
|
|
* {@link TenantServiceImpl} 的单元测试类
|
|
@@ -59,10 +81,118 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
@MockBean
|
|
|
private TenantProducer tenantProducer;
|
|
|
|
|
|
+ @BeforeEach
|
|
|
+ public void setUp() {
|
|
|
+ // 清理缓存
|
|
|
+ ReflectUtil.setFieldValue(tenantService, "tenantCache", Collections.emptyMap());
|
|
|
+ ReflectUtil.setFieldValue(tenantService, "maxUpdateTime", null);
|
|
|
+ // 清理租户上下文
|
|
|
+ TenantContextHolder.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testInitLocalCache() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO tenantDO1 = randomPojo(TenantDO.class);
|
|
|
+ tenantMapper.insert(tenantDO1);
|
|
|
+ TenantDO tenantDO2 = randomPojo(TenantDO.class);
|
|
|
+ tenantMapper.insert(tenantDO2);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.initLocalCache();
|
|
|
+ // 断言 tenantCache 缓存
|
|
|
+ Map<Long, TenantDO> tenantCache = tenantService.getTenantCache();
|
|
|
+ assertEquals(2, tenantCache.size());
|
|
|
+ assertPojoEquals(tenantDO1, tenantCache.get(tenantDO1.getId()));
|
|
|
+ assertPojoEquals(tenantDO2, tenantCache.get(tenantDO2.getId()));
|
|
|
+ // 断言 maxUpdateTime 缓存
|
|
|
+ assertEquals(max(tenantDO1.getUpdateTime(), tenantDO2.getUpdateTime()), tenantService.getMaxUpdateTime());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTenantIds() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L));
|
|
|
+ tenantMapper.insert(tenant);
|
|
|
+ tenantService.initLocalCache();
|
|
|
+
|
|
|
+ // 调用,并断言业务异常
|
|
|
+ List<Long> result = tenantService.getTenantIds();
|
|
|
+ assertEquals(Collections.singletonList(1L), result);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testValidTenant_notExists() {
|
|
|
+ assertServiceException(() -> tenantService.validTenant(randomLongId()), TENANT_NOT_EXISTS);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testValidTenant_disable() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
|
|
+ tenantMapper.insert(tenant);
|
|
|
+ tenantService.initLocalCache();
|
|
|
+
|
|
|
+ // 调用,并断言业务异常
|
|
|
+ assertServiceException(() -> tenantService.validTenant(1L), TENANT_DISABLE, tenant.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testValidTenant_expired() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
|
|
+ .setExpireTime(buildTime(2020, 2, 2)));
|
|
|
+ tenantMapper.insert(tenant);
|
|
|
+ tenantService.initLocalCache();
|
|
|
+
|
|
|
+ // 调用,并断言业务异常
|
|
|
+ assertServiceException(() -> tenantService.validTenant(1L), TENANT_EXPIRE, tenant.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testValidTenant_success() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
|
|
|
+ .setExpireTime(addTime(Duration.ofDays(1))));
|
|
|
+ tenantMapper.insert(tenant);
|
|
|
+ tenantService.initLocalCache();
|
|
|
+
|
|
|
+ // 调用,并断言业务异常
|
|
|
+ tenantService.validTenant(1L);
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
- public void testCreateTenant_success() {
|
|
|
+ public void testCreateTenant() {
|
|
|
+ // mock 套餐 100L
|
|
|
+ TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class, o -> o.setId(100L));
|
|
|
+ when(tenantPackageService.validTenantPackage(eq(100L))).thenReturn(tenantPackage);
|
|
|
+ // mock 角色 200L
|
|
|
+ when(roleService.createRole(argThat(role -> {
|
|
|
+ assertEquals(RoleCodeEnum.TENANT_ADMIN.getName(), role.getName());
|
|
|
+ assertEquals(RoleCodeEnum.TENANT_ADMIN.getCode(), role.getCode());
|
|
|
+ assertEquals(0, role.getSort());
|
|
|
+ assertEquals("系统自动生成", role.getRemark());
|
|
|
+ return true;
|
|
|
+ }), eq(RoleTypeEnum.SYSTEM.getType()))).thenReturn(200L);
|
|
|
+ // mock 用户 300L
|
|
|
+ when(userService.createUser(argThat(user -> {
|
|
|
+ assertEquals("yudao", user.getUsername());
|
|
|
+ assertEquals("yuanma", user.getPassword());
|
|
|
+ assertEquals("芋道", user.getNickname());
|
|
|
+ assertEquals("15601691300", user.getMobile());
|
|
|
+ return true;
|
|
|
+ }))).thenReturn(300L);
|
|
|
+
|
|
|
// 准备参数
|
|
|
- TenantCreateReqVO reqVO = randomPojo(TenantCreateReqVO.class, o -> o.setStatus(randomCommonStatus()));
|
|
|
+ TenantCreateReqVO reqVO = randomPojo(TenantCreateReqVO.class, o -> {
|
|
|
+ o.setContactName("芋道");
|
|
|
+ o.setContactMobile("15601691300");
|
|
|
+ o.setPackageId(100L);
|
|
|
+ o.setStatus(randomCommonStatus());
|
|
|
+ o.setDomain("https://www.iocoder.cn");
|
|
|
+ o.setUsername("yudao");
|
|
|
+ o.setPassword("yuanma");
|
|
|
+ });
|
|
|
|
|
|
// 调用
|
|
|
Long tenantId = tenantService.createTenant(reqVO);
|
|
@@ -71,6 +201,13 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
// 校验记录的属性是否正确
|
|
|
TenantDO tenant = tenantMapper.selectById(tenantId);
|
|
|
assertPojoEquals(reqVO, tenant);
|
|
|
+ assertEquals(300L, tenant.getContactUserId());
|
|
|
+ // verify 分配权限
|
|
|
+ verify(permissionService).assignRoleMenu(eq(200L), same(tenantPackage.getMenuIds()));
|
|
|
+ // verify 分配角色
|
|
|
+ verify(permissionService).assignUserRole(eq(300L), eq(singleton(200L)));
|
|
|
+ // verify 发送刷新消息
|
|
|
+ verify(tenantProducer).sendTenantRefreshMessage();
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -82,13 +219,32 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class, o -> {
|
|
|
o.setId(dbTenant.getId()); // 设置更新的 ID
|
|
|
o.setStatus(randomCommonStatus());
|
|
|
+ o.setDomain(randomString());
|
|
|
});
|
|
|
|
|
|
+ // mock 套餐
|
|
|
+ TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class,
|
|
|
+ o -> o.setMenuIds(asSet(200L, 201L)));
|
|
|
+ when(tenantPackageService.validTenantPackage(eq(reqVO.getPackageId()))).thenReturn(tenantPackage);
|
|
|
+ // mock 所有角色
|
|
|
+ RoleDO role100 = randomPojo(RoleDO.class, o -> o.setId(100L).setCode(RoleCodeEnum.TENANT_ADMIN.getCode()));
|
|
|
+ role100.setTenantId(dbTenant.getId());
|
|
|
+ RoleDO role101 = randomPojo(RoleDO.class, o -> o.setId(101L));
|
|
|
+ role101.setTenantId(dbTenant.getId());
|
|
|
+ when(roleService.getRoles(isNull())).thenReturn(asList(role100, role101));
|
|
|
+ // mock 每个角色的权限
|
|
|
+ when(permissionService.getRoleMenuIds(eq(101L))).thenReturn(asSet(201L, 202L));
|
|
|
+
|
|
|
// 调用
|
|
|
tenantService.updateTenant(reqVO);
|
|
|
// 校验是否更新正确
|
|
|
TenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的
|
|
|
assertPojoEquals(reqVO, tenant);
|
|
|
+ // verify 发送刷新消息
|
|
|
+ verify(tenantProducer).sendTenantRefreshMessage();
|
|
|
+ // verify 设置角色权限
|
|
|
+ verify(permissionService).assignRoleMenu(eq(100L), eq(asSet(200L, 201L)));
|
|
|
+ verify(permissionService).assignRoleMenu(eq(101L), eq(asSet(201L)));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -100,6 +256,20 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS);
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testUpdateTenant_system() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ // 准备参数
|
|
|
+ TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class, o -> {
|
|
|
+ o.setId(dbTenant.getId()); // 设置更新的 ID
|
|
|
+ });
|
|
|
+
|
|
|
+ // 调用,校验业务异常
|
|
|
+ assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_CAN_NOT_UPDATE_SYSTEM);
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void testDeleteTenant_success() {
|
|
|
// mock 数据
|
|
@@ -124,6 +294,32 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
assertServiceException(() -> tenantService.deleteTenant(id), TENANT_NOT_EXISTS);
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testDeleteTenant_system() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ // 准备参数
|
|
|
+ Long id = dbTenant.getId();
|
|
|
+
|
|
|
+ // 调用, 并断言异常
|
|
|
+ assertServiceException(() -> tenantService.deleteTenant(id), TENANT_CAN_NOT_UPDATE_SYSTEM);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTenant() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class);
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ // 准备参数
|
|
|
+ Long id = dbTenant.getId();
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ TenantDO result = tenantService.getTenant(id);
|
|
|
+ // 校验存在
|
|
|
+ assertPojoEquals(result, dbTenant);
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void testGetTenantPage() {
|
|
|
// mock 数据
|
|
@@ -199,4 +395,129 @@ public class TenantServiceImplTest extends BaseDbUnitTest {
|
|
|
assertPojoEquals(dbTenant, list.get(0));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTenantByName() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setName("芋道"));
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ TenantDO result = tenantService.getTenantByName("芋道");
|
|
|
+ // 校验存在
|
|
|
+ assertPojoEquals(result, dbTenant);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTenantListByPackageId() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant1 = randomPojo(TenantDO.class, o -> o.setPackageId(1L));
|
|
|
+ tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
|
|
+ TenantDO dbTenant2 = randomPojo(TenantDO.class, o -> o.setPackageId(2L));
|
|
|
+ tenantMapper.insert(dbTenant2);// @Sql: 先插入出一条存在的数据
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ List<TenantDO> result = tenantService.getTenantListByPackageId(1L);
|
|
|
+ assertEquals(1, result.size());
|
|
|
+ assertPojoEquals(dbTenant1, result.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTenantCountByPackageId() {
|
|
|
+ // mock 数据
|
|
|
+ TenantDO dbTenant1 = randomPojo(TenantDO.class, o -> o.setPackageId(1L));
|
|
|
+ tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
|
|
|
+ TenantDO dbTenant2 = randomPojo(TenantDO.class, o -> o.setPackageId(2L));
|
|
|
+ tenantMapper.insert(dbTenant2);// @Sql: 先插入出一条存在的数据
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ Integer count = tenantService.getTenantCountByPackageId(1L);
|
|
|
+ assertEquals(1, count);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testHandleTenantInfo_disable() {
|
|
|
+ // 准备参数
|
|
|
+ TenantInfoHandler handler = mock(TenantInfoHandler.class);
|
|
|
+ // mock 禁用
|
|
|
+ when(tenantProperties.getEnable()).thenReturn(false);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.handleTenantInfo(handler);
|
|
|
+ // 断言
|
|
|
+ verify(handler, never()).handle(any());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testHandleTenantInfo_success() {
|
|
|
+ // 准备参数
|
|
|
+ TenantInfoHandler handler = mock(TenantInfoHandler.class);
|
|
|
+ // mock 未禁用
|
|
|
+ when(tenantProperties.getEnable()).thenReturn(true);
|
|
|
+ // mock 租户
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class);
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ TenantContextHolder.setTenantId(dbTenant.getId());
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.handleTenantInfo(handler);
|
|
|
+ // 断言
|
|
|
+ verify(handler).handle(argThat(argument -> {
|
|
|
+ assertPojoEquals(dbTenant, argument);
|
|
|
+ return true;
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testHandleTenantMenu_disable() {
|
|
|
+ // 准备参数
|
|
|
+ TenantMenuHandler handler = mock(TenantMenuHandler.class);
|
|
|
+ // mock 禁用
|
|
|
+ when(tenantProperties.getEnable()).thenReturn(false);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.handleTenantMenu(handler);
|
|
|
+ // 断言
|
|
|
+ verify(handler, never()).handle(any());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test // 系统租户的情况
|
|
|
+ public void testHandleTenantMenu_system() {
|
|
|
+ // 准备参数
|
|
|
+ TenantMenuHandler handler = mock(TenantMenuHandler.class);
|
|
|
+ // mock 未禁用
|
|
|
+ when(tenantProperties.getEnable()).thenReturn(true);
|
|
|
+ // mock 租户
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ TenantContextHolder.setTenantId(dbTenant.getId());
|
|
|
+ // mock 菜单
|
|
|
+ when(menuService.getMenus()).thenReturn(Arrays.asList(randomPojo(MenuDO.class, o -> o.setId(100L)),
|
|
|
+ randomPojo(MenuDO.class, o -> o.setId(101L))));
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.handleTenantMenu(handler);
|
|
|
+ // 断言
|
|
|
+ verify(handler).handle(asSet(100L, 101L));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test // 普通租户的情况
|
|
|
+ public void testHandleTenantMenu_normal() {
|
|
|
+ // 准备参数
|
|
|
+ TenantMenuHandler handler = mock(TenantMenuHandler.class);
|
|
|
+ // mock 未禁用
|
|
|
+ when(tenantProperties.getEnable()).thenReturn(true);
|
|
|
+ // mock 租户
|
|
|
+ TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(200L));
|
|
|
+ tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
|
|
|
+ TenantContextHolder.setTenantId(dbTenant.getId());
|
|
|
+ // mock 菜单
|
|
|
+ when(tenantPackageService.getTenantPackage(eq(200L))).thenReturn(randomPojo(TenantPackageDO.class,
|
|
|
+ o -> o.setMenuIds(asSet(100L, 101L))));
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ tenantService.handleTenantMenu(handler);
|
|
|
+ // 断言
|
|
|
+ verify(handler).handle(asSet(100L, 101L));
|
|
|
+ }
|
|
|
}
|