Commit d5fb438f59bf608ada5bc26b933e76a38fdaa64c
Committed by
Gitee
!20 Job 模块单元测试
Merge pull request !20 from neilz/feature/ut-job
Showing
6 changed files
with
509 additions
and
0 deletions
sql/quartz.sql
| @@ -178,3 +178,11 @@ CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIG | @@ -178,3 +178,11 @@ CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIG | ||
| 178 | CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); | 178 | CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP); |
| 179 | 179 | ||
| 180 | commit; | 180 | commit; |
| 181 | + | ||
| 182 | +-- 初始化默认任务 用户 Session 超时 Job | ||
| 183 | +INSERT INTO QRTZ_JOB_DETAILS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 'cn.iocoder.dashboard.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000047400104A4F425F48414E444C45525F4E414D457400187379735573657253657373696F6E54696D656F75744A6F627800); | ||
| 184 | +commit; | ||
| 185 | +INSERT INTO QRTZ_TRIGGERS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 1615706340000, 1615706280000, 5, 'WAITING', 'CRON', 1615706125000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000007D074000F4A4F425F52455452595F434F554E547371007E0009000000037800); | ||
| 186 | +commit; | ||
| 187 | +INSERT INTO QRTZ_CRON_TRIGGERS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', '0 * * * * ? *', 'Asia/Shanghai'); | ||
| 188 | +commit; |
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobBaseVO.java
src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.infra.service.job; | ||
| 2 | + | ||
| 3 | +import static cn.hutool.core.util.RandomUtil.randomEle; | ||
| 4 | +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; | ||
| 5 | +import static cn.iocoder.dashboard.util.RandomUtils.randomLongId; | ||
| 6 | +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo; | ||
| 7 | +import static cn.iocoder.dashboard.util.RandomUtils.randomString; | ||
| 8 | +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; | ||
| 9 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 10 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
| 11 | + | ||
| 12 | +import java.util.ArrayList; | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 15 | +import javax.annotation.Resource; | ||
| 16 | + | ||
| 17 | +import org.junit.jupiter.api.Test; | ||
| 18 | +import org.springframework.context.annotation.Import; | ||
| 19 | + | ||
| 20 | +import cn.iocoder.dashboard.BaseDbUnitTest; | ||
| 21 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 22 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; | ||
| 23 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; | ||
| 24 | +import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO; | ||
| 25 | +import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper; | ||
| 26 | +import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum; | ||
| 27 | +import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobLogServiceImpl; | ||
| 28 | +import cn.iocoder.dashboard.util.object.ObjectUtils; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * {@link InfJobLogServiceImpl} 的单元测试 | ||
| 32 | + * | ||
| 33 | + * @author neilz | ||
| 34 | + */ | ||
| 35 | +@Import(InfJobLogServiceImpl.class) | ||
| 36 | +public class InfJobLogServiceTest extends BaseDbUnitTest { | ||
| 37 | + | ||
| 38 | + @Resource | ||
| 39 | + private InfJobLogServiceImpl jobLogService; | ||
| 40 | + @Resource | ||
| 41 | + private InfJobLogMapper jobLogMapper; | ||
| 42 | + | ||
| 43 | + @Test | ||
| 44 | + public void testCreateJobLog_success() { | ||
| 45 | + // 准备参数 | ||
| 46 | + InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> { | ||
| 47 | + o.setExecuteIndex(1); | ||
| 48 | + }); | ||
| 49 | + // 调用 | ||
| 50 | + Long jobLogId = jobLogService.createJobLog(reqVO.getJobId(), reqVO.getBeginTime(), reqVO.getHandlerName(), reqVO.getHandlerParam(), reqVO.getExecuteIndex()); | ||
| 51 | + // 断言 | ||
| 52 | + assertNotNull(jobLogId); | ||
| 53 | + // 校验记录的属性是否正确 | ||
| 54 | + InfJobLogDO job = jobLogMapper.selectById(jobLogId); | ||
| 55 | + assertEquals(InfJobLogStatusEnum.RUNNING.getStatus(), job.getStatus()); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Test | ||
| 59 | + public void testUpdateJobLogResultAsync_success() { | ||
| 60 | + // 准备参数 | ||
| 61 | + InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> { | ||
| 62 | + o.setExecuteIndex(1); | ||
| 63 | + }); | ||
| 64 | + InfJobLogDO log = InfJobLogDO.builder().jobId(reqVO.getJobId()).handlerName(reqVO.getHandlerName()).handlerParam(reqVO.getHandlerParam()).executeIndex(reqVO.getExecuteIndex()) | ||
| 65 | + .beginTime(reqVO.getBeginTime()).status(InfJobLogStatusEnum.RUNNING.getStatus()).build(); | ||
| 66 | + jobLogMapper.insert(log); | ||
| 67 | + // 调用 | ||
| 68 | + jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), true,reqVO.getResult()); | ||
| 69 | + // 校验记录的属性是否正确 | ||
| 70 | + InfJobLogDO job = jobLogMapper.selectById(log.getId()); | ||
| 71 | + assertEquals(InfJobLogStatusEnum.SUCCESS.getStatus(), job.getStatus()); | ||
| 72 | + | ||
| 73 | + // 调用 | ||
| 74 | + jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), false,reqVO.getResult()); | ||
| 75 | + // 校验记录的属性是否正确 | ||
| 76 | + InfJobLogDO job2 = jobLogMapper.selectById(log.getId()); | ||
| 77 | + assertEquals(InfJobLogStatusEnum.FAILURE.getStatus(), job2.getStatus()); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + @Test | ||
| 81 | + public void testGetJobLogListByIds_success() { | ||
| 82 | + // mock 数据 | ||
| 83 | + InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { | ||
| 84 | + o.setExecuteIndex(1); | ||
| 85 | + o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围 | ||
| 86 | + }); | ||
| 87 | + InfJobLogDO cloneJobLog = ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())); | ||
| 88 | + jobLogMapper.insert(dbJobLog); | ||
| 89 | + // 测试 handlerName 不匹配 | ||
| 90 | + jobLogMapper.insert(cloneJobLog); | ||
| 91 | + // 准备参数 | ||
| 92 | + ArrayList ids = new ArrayList<>(); | ||
| 93 | + ids.add(dbJobLog.getId()); | ||
| 94 | + ids.add(cloneJobLog.getId()); | ||
| 95 | + // 调用 | ||
| 96 | + List<InfJobLogDO> list = jobLogService.getJobLogList(ids); | ||
| 97 | + // 断言 | ||
| 98 | + assertEquals(2, list.size()); | ||
| 99 | + assertPojoEquals(dbJobLog, list.get(0)); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + @Test | ||
| 103 | + public void testGetJobPage_success() { | ||
| 104 | + // mock 数据 | ||
| 105 | + InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { | ||
| 106 | + o.setExecuteIndex(1); | ||
| 107 | + o.setHandlerName("handlerName 单元测试"); | ||
| 108 | + o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); | ||
| 109 | + o.setBeginTime(buildTime(2021, 1, 8)); | ||
| 110 | + o.setEndTime(buildTime(2021, 1, 8)); | ||
| 111 | + }); | ||
| 112 | + jobLogMapper.insert(dbJobLog); | ||
| 113 | + // 测试 jobId 不匹配 | ||
| 114 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId()))); | ||
| 115 | + // 测试 handlerName 不匹配 | ||
| 116 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString()))); | ||
| 117 | + // 测试 beginTime 不匹配 | ||
| 118 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7)))); | ||
| 119 | + // 测试 endTime 不匹配 | ||
| 120 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); | ||
| 121 | + // 测试 status 不匹配 | ||
| 122 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus()))); | ||
| 123 | + // 准备参数 | ||
| 124 | + InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO(); | ||
| 125 | + reqVo.setJobId(dbJobLog.getJobId()); | ||
| 126 | + reqVo.setHandlerName("单元"); | ||
| 127 | + reqVo.setBeginTime(dbJobLog.getBeginTime()); | ||
| 128 | + reqVo.setEndTime(dbJobLog.getEndTime()); | ||
| 129 | + reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); | ||
| 130 | + // 调用 | ||
| 131 | + PageResult<InfJobLogDO> pageResult = jobLogService.getJobLogPage(reqVo); | ||
| 132 | + // 断言 | ||
| 133 | + assertEquals(1, pageResult.getTotal()); | ||
| 134 | + assertEquals(1, pageResult.getList().size()); | ||
| 135 | + assertPojoEquals(dbJobLog, pageResult.getList().get(0)); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Test | ||
| 139 | + public void testGetJobListForExport_success() { | ||
| 140 | + // mock 数据 | ||
| 141 | + InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { | ||
| 142 | + o.setExecuteIndex(1); | ||
| 143 | + o.setHandlerName("handlerName 单元测试"); | ||
| 144 | + o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); | ||
| 145 | + o.setBeginTime(buildTime(2021, 1, 8)); | ||
| 146 | + o.setEndTime(buildTime(2021, 1, 8)); | ||
| 147 | + }); | ||
| 148 | + jobLogMapper.insert(dbJobLog); | ||
| 149 | + // 测试 jobId 不匹配 | ||
| 150 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId()))); | ||
| 151 | + // 测试 handlerName 不匹配 | ||
| 152 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString()))); | ||
| 153 | + // 测试 beginTime 不匹配 | ||
| 154 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7)))); | ||
| 155 | + // 测试 endTime 不匹配 | ||
| 156 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); | ||
| 157 | + // 测试 status 不匹配 | ||
| 158 | + jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus()))); | ||
| 159 | + // 准备参数 | ||
| 160 | + InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO(); | ||
| 161 | + reqVo.setJobId(dbJobLog.getJobId()); | ||
| 162 | + reqVo.setHandlerName("单元"); | ||
| 163 | + reqVo.setBeginTime(dbJobLog.getBeginTime()); | ||
| 164 | + reqVo.setEndTime(dbJobLog.getEndTime()); | ||
| 165 | + reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); | ||
| 166 | + // 调用 | ||
| 167 | + List<InfJobLogDO> list = jobLogService.getJobLogList(reqVo); | ||
| 168 | + // 断言 | ||
| 169 | + assertEquals(1, list.size()); | ||
| 170 | + assertPojoEquals(dbJobLog, list.get(0)); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | +} |
src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.infra.service.job; | ||
| 2 | + | ||
| 3 | +import static cn.hutool.core.util.RandomUtil.randomEle; | ||
| 4 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_EQUALS; | ||
| 5 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_INVALID; | ||
| 6 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CRON_EXPRESSION_VALID; | ||
| 7 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_HANDLER_EXISTS; | ||
| 8 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_NOT_EXISTS; | ||
| 9 | +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_UPDATE_ONLY_NORMAL_STATUS; | ||
| 10 | +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; | ||
| 11 | +import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException; | ||
| 12 | +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo; | ||
| 13 | +import static cn.iocoder.dashboard.util.RandomUtils.randomString; | ||
| 14 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 15 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
| 16 | +import static org.junit.jupiter.api.Assertions.assertNull; | ||
| 17 | + | ||
| 18 | +import java.util.ArrayList; | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 21 | +import javax.annotation.Resource; | ||
| 22 | + | ||
| 23 | +import org.junit.jupiter.api.Test; | ||
| 24 | +import org.quartz.SchedulerException; | ||
| 25 | +import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 26 | +import org.springframework.context.annotation.Import; | ||
| 27 | + | ||
| 28 | +import cn.iocoder.dashboard.BaseDbUnitTest; | ||
| 29 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 30 | +import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager; | ||
| 31 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO; | ||
| 32 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO; | ||
| 33 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO; | ||
| 34 | +import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO; | ||
| 35 | +import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert; | ||
| 36 | +import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO; | ||
| 37 | +import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper; | ||
| 38 | +import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum; | ||
| 39 | +import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobServiceImpl; | ||
| 40 | +import cn.iocoder.dashboard.util.object.ObjectUtils; | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | + * {@link InfJobServiceImpl} 的单元测试 | ||
| 44 | + * | ||
| 45 | + * @author neilz | ||
| 46 | + */ | ||
| 47 | +@Import(InfJobServiceImpl.class) | ||
| 48 | +public class InfJobServiceTest extends BaseDbUnitTest { | ||
| 49 | + | ||
| 50 | + @Resource | ||
| 51 | + private InfJobServiceImpl jobService; | ||
| 52 | + @Resource | ||
| 53 | + private InfJobMapper jobMapper; | ||
| 54 | + @MockBean | ||
| 55 | + private SchedulerManager schedulerManager; | ||
| 56 | + | ||
| 57 | + @Test | ||
| 58 | + public void testCreateJob_cronExpressionValid() { | ||
| 59 | + // 准备参数。Cron 表达式为 String 类型,默认随机字符串。 | ||
| 60 | + InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class); | ||
| 61 | + // 调用,并断言异常 | ||
| 62 | + assertServiceException(() -> jobService.createJob(reqVO), JOB_CRON_EXPRESSION_VALID); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Test | ||
| 66 | + public void testCreateJob_jobHandlerExists() throws SchedulerException { | ||
| 67 | + // 准备参数 指定 Cron 表达式 | ||
| 68 | + InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 69 | + // 调用 | ||
| 70 | + jobService.createJob(reqVO); | ||
| 71 | + // 调用,并断言异常 | ||
| 72 | + assertServiceException(() -> jobService.createJob(reqVO), JOB_HANDLER_EXISTS); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @Test | ||
| 76 | + public void testCreateJob_success() throws SchedulerException { | ||
| 77 | + // 准备参数 指定 Cron 表达式 | ||
| 78 | + InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 79 | + // 调用 | ||
| 80 | + Long jobId = jobService.createJob(reqVO); | ||
| 81 | + // 断言 | ||
| 82 | + assertNotNull(jobId); | ||
| 83 | + // 校验记录的属性是否正确 | ||
| 84 | + InfJobDO job = jobMapper.selectById(jobId); | ||
| 85 | + assertPojoEquals(reqVO, job); | ||
| 86 | + assertEquals(InfJobStatusEnum.NORMAL.getStatus(), job.getStatus()); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @Test | ||
| 90 | + public void testUpdateJob_jobNotExists(){ | ||
| 91 | + // 准备参数 | ||
| 92 | + InfJobUpdateReqVO reqVO = randomPojo(InfJobUpdateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 93 | + // 调用,并断言异常 | ||
| 94 | + assertServiceException(() -> jobService.updateJob(reqVO), JOB_NOT_EXISTS); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + @Test | ||
| 98 | + public void testUpdateJob_onlyNormalStatus(){ | ||
| 99 | + // mock 数据 | ||
| 100 | + InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 101 | + InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); | ||
| 102 | + job.setStatus(InfJobStatusEnum.INIT.getStatus()); | ||
| 103 | + fillJobMonitorTimeoutEmpty(job); | ||
| 104 | + jobMapper.insert(job); | ||
| 105 | + // 准备参数 | ||
| 106 | + InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> { | ||
| 107 | + o.setId(job.getId()); | ||
| 108 | + o.setName(createReqVO.getName()); | ||
| 109 | + o.setCronExpression(createReqVO.getCronExpression()); | ||
| 110 | + }); | ||
| 111 | + // 调用,并断言异常 | ||
| 112 | + assertServiceException(() -> jobService.updateJob(updateReqVO), JOB_UPDATE_ONLY_NORMAL_STATUS); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Test | ||
| 116 | + public void testUpdateJob_success() throws SchedulerException { | ||
| 117 | + // mock 数据 | ||
| 118 | + InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 119 | + InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); | ||
| 120 | + job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); | ||
| 121 | + fillJobMonitorTimeoutEmpty(job); | ||
| 122 | + jobMapper.insert(job); | ||
| 123 | + schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), | ||
| 124 | + createReqVO.getRetryCount(), createReqVO.getRetryInterval()); | ||
| 125 | + // 准备参数 | ||
| 126 | + InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> { | ||
| 127 | + o.setId(job.getId()); | ||
| 128 | + o.setName(createReqVO.getName()); | ||
| 129 | + o.setCronExpression(createReqVO.getCronExpression()); | ||
| 130 | + }); | ||
| 131 | + // 调用 | ||
| 132 | + jobService.updateJob(updateReqVO); | ||
| 133 | + // 校验记录的属性是否正确 | ||
| 134 | + InfJobDO updateJob = jobMapper.selectById(updateReqVO.getId()); | ||
| 135 | + assertPojoEquals(updateReqVO, updateJob); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Test | ||
| 139 | + public void testUpdateJobStatus_changeStatusInvalid() { | ||
| 140 | + // 调用,并断言异常 | ||
| 141 | + assertServiceException(() -> jobService.updateJobStatus(1l, InfJobStatusEnum.INIT.getStatus()), JOB_CHANGE_STATUS_INVALID); | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + @Test | ||
| 145 | + public void testUpdateJobStatus_changeStatusEquals() { | ||
| 146 | + // mock 数据 | ||
| 147 | + InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 148 | + InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); | ||
| 149 | + job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); | ||
| 150 | + fillJobMonitorTimeoutEmpty(job); | ||
| 151 | + jobMapper.insert(job); | ||
| 152 | + // 调用,并断言异常 | ||
| 153 | + assertServiceException(() -> jobService.updateJobStatus(job.getId(), job.getStatus()), JOB_CHANGE_STATUS_EQUALS); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + @Test | ||
| 157 | + public void testUpdateJobStatus_success() throws SchedulerException { | ||
| 158 | + // mock 数据 | ||
| 159 | + InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 160 | + InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); | ||
| 161 | + job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); | ||
| 162 | + fillJobMonitorTimeoutEmpty(job); | ||
| 163 | + jobMapper.insert(job); | ||
| 164 | + schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), | ||
| 165 | + createReqVO.getRetryCount(), createReqVO.getRetryInterval()); | ||
| 166 | + // 调用 | ||
| 167 | + jobService.updateJobStatus(job.getId(), InfJobStatusEnum.STOP.getStatus()); | ||
| 168 | + // 校验记录的属性是否正确 | ||
| 169 | + InfJobDO updateJob = jobMapper.selectById(job.getId()); | ||
| 170 | + assertEquals(InfJobStatusEnum.STOP.getStatus(), updateJob.getStatus()); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + /** | ||
| 174 | + * 页面"执行一次"按钮功能集成测试发现问题: | ||
| 175 | + * inf_job 表初始化任务 sysUserSessionTimeoutJob 点击报错,是因为 Job 并没有添加到 Quartz 中; | ||
| 176 | + * 没有走 createJob 中 scheduler.scheduleJob() 这一步,报错任务找不到。 | ||
| 177 | + * // FINISHED Quartz 相关表新增初始化任务 sysUserSessionTimeoutJob sql | ||
| 178 | + */ | ||
| 179 | + @Test | ||
| 180 | + public void testTriggerJob_success() throws SchedulerException { | ||
| 181 | + /** | ||
| 182 | + * TODO 不知道是否要将 Quartz 相关 SQL 引入来做单元测试 | ||
| 183 | + * 1、schedulerManager.addJob sysUserSessionTimeoutJob | ||
| 184 | + * 2、schedulerManager.triggerJob | ||
| 185 | + * 3、check inf_job_log | ||
| 186 | + */ | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + @Test | ||
| 190 | + public void testDeleteJob_success() throws SchedulerException { | ||
| 191 | + // mock 数据 | ||
| 192 | + InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); | ||
| 193 | + InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); | ||
| 194 | + job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); | ||
| 195 | + fillJobMonitorTimeoutEmpty(job); | ||
| 196 | + jobMapper.insert(job); | ||
| 197 | + schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), | ||
| 198 | + createReqVO.getRetryCount(), createReqVO.getRetryInterval()); | ||
| 199 | + // 调用 UPDATE inf_job SET deleted=1 WHERE id=? AND deleted=0 | ||
| 200 | + jobService.deleteJob(job.getId()); | ||
| 201 | + // 校验数据不存在了 WHERE id=? AND deleted=0 查询为空正常 | ||
| 202 | + assertNull(jobMapper.selectById(job.getId())); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + @Test | ||
| 206 | + public void testGetJobListByIds_success() { | ||
| 207 | + // mock 数据 | ||
| 208 | + InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { | ||
| 209 | + o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围 | ||
| 210 | + }); | ||
| 211 | + InfJobDO cloneJob = ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())); | ||
| 212 | + jobMapper.insert(dbJob); | ||
| 213 | + // 测试 handlerName 不匹配 | ||
| 214 | + jobMapper.insert(cloneJob); | ||
| 215 | + // 准备参数 | ||
| 216 | + ArrayList ids = new ArrayList<>(); | ||
| 217 | + ids.add(dbJob.getId()); | ||
| 218 | + ids.add(cloneJob.getId()); | ||
| 219 | + // 调用 | ||
| 220 | + List<InfJobDO> list = jobService.getJobList(ids); | ||
| 221 | + // 断言 | ||
| 222 | + assertEquals(2, list.size()); | ||
| 223 | + assertPojoEquals(dbJob, list.get(0)); | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + @Test | ||
| 227 | + public void testGetJobPage_success() { | ||
| 228 | + // mock 数据 | ||
| 229 | + InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { | ||
| 230 | + o.setName("定时任务测试"); | ||
| 231 | + o.setHandlerName("handlerName 单元测试"); | ||
| 232 | + o.setStatus(InfJobStatusEnum.INIT.getStatus()); | ||
| 233 | + }); | ||
| 234 | + jobMapper.insert(dbJob); | ||
| 235 | + // 测试 name 不匹配 | ||
| 236 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆"))); | ||
| 237 | + // 测试 status 不匹配 | ||
| 238 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus()))); | ||
| 239 | + // 测试 handlerName 不匹配 | ||
| 240 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString()))); | ||
| 241 | + // 准备参数 | ||
| 242 | + InfJobPageReqVO reqVo = new InfJobPageReqVO(); | ||
| 243 | + reqVo.setName("定时"); | ||
| 244 | + reqVo.setStatus(InfJobStatusEnum.INIT.getStatus()); | ||
| 245 | + reqVo.setHandlerName("单元"); | ||
| 246 | + // 调用 | ||
| 247 | + PageResult<InfJobDO> pageResult = jobService.getJobPage(reqVo); | ||
| 248 | + // 断言 | ||
| 249 | + assertEquals(1, pageResult.getTotal()); | ||
| 250 | + assertEquals(1, pageResult.getList().size()); | ||
| 251 | + assertPojoEquals(dbJob, pageResult.getList().get(0)); | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + @Test | ||
| 255 | + public void testGetJobListForExport_success() { | ||
| 256 | + // mock 数据 | ||
| 257 | + InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { | ||
| 258 | + o.setName("定时任务测试"); | ||
| 259 | + o.setHandlerName("handlerName 单元测试"); | ||
| 260 | + o.setStatus(InfJobStatusEnum.INIT.getStatus()); | ||
| 261 | + }); | ||
| 262 | + jobMapper.insert(dbJob); | ||
| 263 | + // 测试 name 不匹配 | ||
| 264 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆"))); | ||
| 265 | + // 测试 status 不匹配 | ||
| 266 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus()))); | ||
| 267 | + // 测试 handlerName 不匹配 | ||
| 268 | + jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString()))); | ||
| 269 | + // 准备参数 | ||
| 270 | + InfJobExportReqVO reqVo = new InfJobExportReqVO(); | ||
| 271 | + reqVo.setName("定时"); | ||
| 272 | + reqVo.setStatus(InfJobStatusEnum.INIT.getStatus()); | ||
| 273 | + reqVo.setHandlerName("单元"); | ||
| 274 | + // 调用 | ||
| 275 | + List<InfJobDO> list = jobService.getJobList(reqVo); | ||
| 276 | + // 断言 | ||
| 277 | + assertEquals(1, list.size()); | ||
| 278 | + assertPojoEquals(dbJob, list.get(0)); | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + private static void fillJobMonitorTimeoutEmpty(InfJobDO job) { | ||
| 282 | + if (job.getMonitorTimeout() == null) { | ||
| 283 | + job.setMonitorTimeout(0); | ||
| 284 | + } | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | +} |
src/test/resources/sql/clean.sql
src/test/resources/sql/create_tables.sql
| @@ -29,6 +29,44 @@ CREATE TABLE IF NOT EXISTS "inf_file" ( | @@ -29,6 +29,44 @@ CREATE TABLE IF NOT EXISTS "inf_file" ( | ||
| 29 | PRIMARY KEY ("id") | 29 | PRIMARY KEY ("id") |
| 30 | ) COMMENT '文件表'; | 30 | ) COMMENT '文件表'; |
| 31 | 31 | ||
| 32 | +CREATE TABLE IF NOT EXISTS "inf_job" ( | ||
| 33 | + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '任务编号', | ||
| 34 | + "name" varchar(32) NOT NULL COMMENT '任务名称', | ||
| 35 | + "status" tinyint(4) NOT NULL COMMENT '任务状态', | ||
| 36 | + "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', | ||
| 37 | + "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', | ||
| 38 | + "cron_expression" varchar(32) NOT NULL COMMENT 'CRON 表达式', | ||
| 39 | + "retry_count" int(11) NOT NULL DEFAULT '0' COMMENT '重试次数', | ||
| 40 | + "retry_interval" int(11) NOT NULL DEFAULT '0' COMMENT '重试间隔', | ||
| 41 | + "monitor_timeout" int(11) NOT NULL DEFAULT '0' COMMENT '监控超时时间', | ||
| 42 | + "creator" varchar(64) DEFAULT '' COMMENT '创建者', | ||
| 43 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 44 | + "updater" varchar(64) DEFAULT '' COMMENT '更新者', | ||
| 45 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 46 | + "deleted" bit NOT NULL DEFAULT FALSE COMMENT '是否删除', | ||
| 47 | + PRIMARY KEY ("id") | ||
| 48 | +) COMMENT='定时任务表'; | ||
| 49 | + | ||
| 50 | +DROP TABLE IF EXISTS "inf_job_log"; | ||
| 51 | +CREATE TABLE "inf_job_log" ( | ||
| 52 | + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '日志编号', | ||
| 53 | + "job_id" bigint(20) NOT NULL COMMENT '任务编号', | ||
| 54 | + "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', | ||
| 55 | + "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', | ||
| 56 | + "execute_index" tinyint(4) NOT NULL DEFAULT '1' COMMENT '第几次执行', | ||
| 57 | + "begin_time" datetime NOT NULL COMMENT '开始执行时间', | ||
| 58 | + "end_time" datetime DEFAULT NULL COMMENT '结束执行时间', | ||
| 59 | + "duration" int(11) DEFAULT NULL COMMENT '执行时长', | ||
| 60 | + "status" tinyint(4) NOT NULL COMMENT '任务状态', | ||
| 61 | + "result" varchar(4000) DEFAULT '' COMMENT '结果数据', | ||
| 62 | + "creator" varchar(64) DEFAULT '' COMMENT '创建者', | ||
| 63 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||
| 64 | + "updater" varchar(64) DEFAULT '' COMMENT '更新者', | ||
| 65 | + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||
| 66 | + "deleted" bit(1) NOT NULL DEFAULT FALSE COMMENT '是否删除', | ||
| 67 | + PRIMARY KEY ("id") | ||
| 68 | +)COMMENT='定时任务日志表'; | ||
| 69 | + | ||
| 32 | -- sys 开头的 DB | 70 | -- sys 开头的 DB |
| 33 | 71 | ||
| 34 | CREATE TABLE IF NOT EXISTS "sys_dept" ( | 72 | CREATE TABLE IF NOT EXISTS "sys_dept" ( |