Files
jsowell-charger-web/jsowell-admin/src/test/java/com/jsowell/system/service/TodoTaskServiceImplTest.java
2026-07-16 16:20:34 +08:00

150 lines
5.4 KiB
Java

package com.jsowell.system.service;
import com.jsowell.common.exception.ServiceException;
import com.jsowell.system.constant.TodoTaskConstants;
import com.jsowell.system.domain.SysTodoTask;
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
import com.jsowell.system.domain.dto.TodoTaskQuery;
import com.jsowell.system.mapper.SysTodoTaskMapper;
import com.jsowell.system.service.impl.TodoTaskServiceImpl;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.dao.DuplicateKeyException;
import java.lang.reflect.Field;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
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.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class TodoTaskServiceImplTest {
@Test
void createTask_shouldSetDefaultsAndInsert() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
TodoTaskCreateCommand command = createCommand();
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(null);
doAnswer(invocation -> {
SysTodoTask task = invocation.getArgument(0);
task.setTodoId(11L);
return 1;
}).when(mapper).insertTodoTask(any(SysTodoTask.class));
SysTodoTask result = service.createTask(command);
ArgumentCaptor<SysTodoTask> captor = ArgumentCaptor.forClass(SysTodoTask.class);
verify(mapper).insertTodoTask(captor.capture());
SysTodoTask inserted = captor.getValue();
assertEquals(11L, result.getTodoId());
assertEquals(TodoTaskConstants.PRIORITY_NORMAL, inserted.getPriority());
assertEquals(TodoTaskConstants.STATUS_PENDING, inserted.getTaskStatus());
assertEquals(TodoTaskConstants.READ_UNREAD, inserted.getReadStatus());
assertEquals(inserted.getIdempotentKey(), inserted.getActiveIdempotentKey());
}
@Test
void createTask_shouldReturnExistingTask() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
SysTodoTask existing = new SysTodoTask();
existing.setTodoId(12L);
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(existing);
SysTodoTask result = service.createTask(createCommand());
assertSame(existing, result);
verify(mapper, never()).insertTodoTask(any(SysTodoTask.class));
}
@Test
void createTask_shouldRecoverFromConcurrentDuplicate() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
SysTodoTask existing = new SysTodoTask();
existing.setTodoId(13L);
when(mapper.selectActiveByIdempotentKey("INVOICE:100:8")).thenReturn(null, existing);
doThrow(new DuplicateKeyException("duplicate"))
.when(mapper).insertTodoTask(any(SysTodoTask.class));
SysTodoTask result = service.createTask(createCommand());
assertSame(existing, result);
}
@Test
void listForAssignee_shouldOverrideRequestedUser() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
TodoTaskQuery query = new TodoTaskQuery();
query.setAssigneeUserId(999L);
when(mapper.selectTodoList(query)).thenReturn(Collections.emptyList());
service.listForAssignee(query, 8L);
assertEquals(8L, query.getAssigneeUserId());
verify(mapper).selectTodoList(query);
}
@Test
void complete_shouldBeIdempotentWhenAlreadyCompleted() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
SysTodoTask completed = new SysTodoTask();
completed.setTaskStatus(TodoTaskConstants.STATUS_COMPLETED);
when(mapper.completeTodoForAssignee(20L, 8L, 8L, "tester")).thenReturn(0);
when(mapper.selectTodoByIdForAssignee(20L, 8L)).thenReturn(completed);
assertTrue(service.complete(20L, 8L, "tester"));
}
@Test
void complete_shouldRejectCancelledTask() {
SysTodoTaskMapper mapper = mock(SysTodoTaskMapper.class);
TodoTaskServiceImpl service = newService(mapper);
SysTodoTask cancelled = new SysTodoTask();
cancelled.setTaskStatus(TodoTaskConstants.STATUS_CANCELLED);
when(mapper.completeTodoForAssignee(20L, 8L, 8L, "tester")).thenReturn(0);
when(mapper.selectTodoByIdForAssignee(20L, 8L)).thenReturn(cancelled);
assertThrows(ServiceException.class, () -> service.complete(20L, 8L, "tester"));
}
private static TodoTaskCreateCommand createCommand() {
return TodoTaskCreateCommand.builder()
.taskType("INVOICE_REVIEW")
.title("司机开票申请")
.businessType("INVOICE_APPLY")
.businessId("100")
.routeName("InvoiceApplyDetail")
.assigneeUserId(8L)
.idempotentKey("INVOICE:100:8")
.createBy("tester")
.build();
}
private static TodoTaskServiceImpl newService(SysTodoTaskMapper mapper) {
TodoTaskServiceImpl service = new TodoTaskServiceImpl();
setField(service, "todoTaskMapper", mapper);
return service;
}
private static void setField(Object target, String fieldName, Object value) {
try {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}