15 changed files with 464 additions and 52 deletions
-
13build.gradle
-
BINmatrix-spray.db
-
47src/main/java/com/qyft/ms/app/common/generator/PathGenerator.java
-
56src/main/java/com/qyft/ms/app/common/generator/RectangleGrid.java
-
26src/main/java/com/qyft/ms/app/controller/CMDController.java
-
8src/main/java/com/qyft/ms/app/controller/MatrixCraftController.java
-
11src/main/java/com/qyft/ms/app/model/vo/MatrixCraftResult.java
-
57src/main/java/com/qyft/ms/app/service/CMDService.java
-
5src/main/java/com/qyft/ms/app/service/MatrixCraftService.java
-
3src/main/java/com/qyft/ms/app/service/WebSocketService.java
-
2src/main/java/com/qyft/ms/app/service/impl/ISysSettingsServiceImpl.java
-
31src/main/java/com/qyft/ms/app/service/impl/MatrixCraftServiceImpl.java
-
2src/main/resources/application.yml
-
144src/test/java/com/qyft/ms/CMDServiceTest.java
-
111src/test/java/com/qyft/ms/SprayTest.java
@ -0,0 +1,56 @@ |
|||
package com.qyft.ms.app.common.generator; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
public class RectangleGrid { |
|||
|
|||
public static void main(String[] args) { |
|||
// 示例输入 |
|||
int x1 = 0, y1 = 0; // 左上角坐标 |
|||
int x2 = 10, y2 = 10; // 右下角坐标 |
|||
int spacing = 2; // 间距值 |
|||
String moveType = "horizontal"; // 移动类型:horizontal(横向)或 vertical(纵向) |
|||
|
|||
// 生成坐标点 |
|||
List<int[]> points = generatePoints(x1, y1, x2, y2, spacing, moveType); |
|||
|
|||
// 输出结果 |
|||
for (int[] point : points) { |
|||
System.out.println("(" + point[0] + ", " + point[1] + ")"); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 生成铺满矩形区域的坐标点 |
|||
* |
|||
* @param x1 左上角 x 坐标 |
|||
* @param y1 左上角 y 坐标 |
|||
* @param x2 右下角 x 坐标 |
|||
* @param y2 右下角 y 坐标 |
|||
* @param spacing 间距值 |
|||
* @param moveType 移动类型:horizontal(横向)或 vertical(纵向) |
|||
* @return 坐标点列表 |
|||
*/ |
|||
public static List<int[]> generatePoints(int x1, int y1, int x2, int y2, int spacing, String moveType) { |
|||
List<int[]> points = new ArrayList<>(); |
|||
|
|||
if (moveType.equalsIgnoreCase("horizontal")) { |
|||
// 横向移动:每一行的起点和终点 |
|||
for (int y = y1; y <= y2; y += spacing) { |
|||
points.add(new int[]{x1, y}); // 起点 |
|||
points.add(new int[]{x2, y}); // 终点 |
|||
} |
|||
} else if (moveType.equalsIgnoreCase("vertical")) { |
|||
// 纵向移动:每一列的起点和终点 |
|||
for (int x = x1; x <= x2; x += spacing) { |
|||
points.add(new int[]{x, y1}); // 起点 |
|||
points.add(new int[]{x, y2}); // 终点 |
|||
} |
|||
} else { |
|||
throw new IllegalArgumentException("Invalid move type. Use 'horizontal' or 'vertical'."); |
|||
} |
|||
|
|||
return points; |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
package com.qyft.ms.app.model.vo; |
|||
|
|||
import com.qyft.ms.app.model.entity.MatrixCraft; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class MatrixCraftResult extends MatrixCraft { |
|||
|
|||
private String matrixName; |
|||
|
|||
} |
@ -0,0 +1,144 @@ |
|||
package com.qyft.ms; |
|||
|
|||
import com.qyft.ms.app.model.form.CMDForm; |
|||
import com.qyft.ms.app.model.vo.ExecutionResult; |
|||
import com.qyft.ms.app.service.CMDService; |
|||
import com.qyft.ms.app.service.OperationLogService; |
|||
import com.qyft.ms.app.service.WebSocketService; |
|||
import com.qyft.ms.device.service.DeviceTcpCMDService; |
|||
import org.junit.jupiter.api.BeforeEach; |
|||
import org.junit.jupiter.api.Test; |
|||
import org.mockito.InjectMocks; |
|||
import org.mockito.Mock; |
|||
import org.mockito.MockitoAnnotations; |
|||
import org.springframework.boot.test.context.SpringBootTest; |
|||
import org.springframework.test.context.ActiveProfiles; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.function.Supplier; |
|||
|
|||
import static org.junit.jupiter.api.Assertions.*; |
|||
import static org.mockito.ArgumentMatchers.*; |
|||
import static org.mockito.Mockito.*; |
|||
|
|||
@ActiveProfiles("test") |
|||
@SpringBootTest |
|||
public class CMDServiceTest { |
|||
|
|||
@Mock |
|||
private DeviceTcpCMDService deviceTcpCMDService; |
|||
|
|||
@Mock |
|||
private WebSocketService webSocketService; |
|||
|
|||
@Mock |
|||
private OperationLogService operationLogService; |
|||
|
|||
@InjectMocks |
|||
private CMDService cmdService; |
|||
|
|||
private CMDForm form; |
|||
|
|||
@BeforeEach |
|||
void setUp() { |
|||
MockitoAnnotations.openMocks(this); |
|||
form = new CMDForm(); |
|||
form.setCommandId("test-command"); |
|||
form.setCommandName("test-command"); |
|||
} |
|||
|
|||
@Test |
|||
void testMoveMotorToPosition_Success() { |
|||
// 准备参数 |
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("axis", "x"); |
|||
params.put("position", 100.0); |
|||
form.setParams(params); |
|||
|
|||
// 模拟设备服务调用 |
|||
when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); |
|||
|
|||
// 执行测试 |
|||
boolean result = cmdService.moveMotorToPosition(form); |
|||
|
|||
// 验证结果 |
|||
assertTrue(result); |
|||
verify(deviceTcpCMDService, times(1)).moveMotorToPosition("x", 100.0); |
|||
} |
|||
|
|||
@Test |
|||
void testStartWork_InvalidPosition() { |
|||
// 准备无效参数 |
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("position", new ArrayList<>()); // 空位置列表 |
|||
form.setParams(params); |
|||
|
|||
// 执行测试 |
|||
String result = cmdService.startWork(form); |
|||
|
|||
// 验证返回错误信息 |
|||
assertEquals("position参数错误", result); |
|||
} |
|||
|
|||
@Test |
|||
void testStartWork_PathGeneration() { |
|||
// 准备有效参数 |
|||
Map<String, Object> params = new HashMap<>(); |
|||
List<Map<String, Integer>> positions = new ArrayList<>(); |
|||
Map<String, Integer> pos = new HashMap<>(); |
|||
pos.put("x1", 10); |
|||
pos.put("y1", 20); |
|||
pos.put("x2", 30); |
|||
pos.put("y2", 40); |
|||
pos.put("index", 0); |
|||
positions.add(pos); |
|||
params.put("position", positions); |
|||
params.put("space", 5); |
|||
params.put("routeType", 1); |
|||
params.put("height", 50); |
|||
params.put("movementSpeed", 100); |
|||
form.setParams(params); |
|||
|
|||
// 模拟依赖项 |
|||
when(deviceTcpCMDService.switchThreeWayValveToSpray()).thenReturn(true); |
|||
when(deviceTcpCMDService.setMotorSpeed(anyString(), anyInt())).thenReturn(true); |
|||
when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); |
|||
|
|||
// 执行测试 |
|||
String result = cmdService.startWork(form); |
|||
|
|||
// 验证命令链长度 |
|||
assertNotNull(result); |
|||
verify(deviceTcpCMDService, atLeastOnce()).switchThreeWayValveToSpray(); |
|||
} |
|||
|
|||
@Test |
|||
void testControlValve_NozzleOpen() { |
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("valveType", "Nozzle"); |
|||
params.put("isOpen", true); |
|||
form.setParams(params); |
|||
|
|||
when(deviceTcpCMDService.controlValve(anyString(), anyBoolean())).thenReturn(true); |
|||
|
|||
boolean result = cmdService.controlValve(form); |
|||
assertTrue(result); |
|||
verify(deviceTcpCMDService).controlValve("Nozzle", true); |
|||
} |
|||
|
|||
@Test |
|||
void testRun_CommandFailure() { |
|||
// 模拟一个失败的指令 |
|||
List<Supplier<Boolean>> cmdList = new ArrayList<>(); |
|||
cmdList.add(() -> false); // 直接返回失败 |
|||
|
|||
// 执行内部方法 |
|||
cmdService.run(cmdList, form); |
|||
|
|||
// 验证WebSocket错误消息推送 |
|||
verify(webSocketService).pushMsg(any(), any(ExecutionResult.class)); |
|||
} |
|||
} |
@ -0,0 +1,111 @@ |
|||
package com.qyft.ms; |
|||
|
|||
import com.qyft.ms.app.model.entity.OperationLog; |
|||
import com.qyft.ms.app.model.entity.SysSettings; |
|||
import com.qyft.ms.app.model.form.CMDForm; |
|||
import com.qyft.ms.app.service.*; |
|||
import com.qyft.ms.device.service.DeviceTcpCMDService; |
|||
import org.junit.jupiter.api.BeforeEach; |
|||
import org.junit.jupiter.api.Test; |
|||
import org.mockito.*; |
|||
|
|||
import java.util.*; |
|||
|
|||
import static com.qyft.ms.app.common.generator.PathGenerator.generatePathPoints; |
|||
import static org.mockito.Mockito.*; |
|||
|
|||
public class SprayTest { |
|||
|
|||
@InjectMocks |
|||
private CMDService cmdService; |
|||
|
|||
@Mock |
|||
private WebSocketService webSocketService; |
|||
@Mock |
|||
private DeviceTcpCMDService deviceTcpCMDService; |
|||
@Mock |
|||
private OperationLogService operationLogService; |
|||
@Mock |
|||
private MatrixCraftService matrixCraftService; |
|||
@Mock |
|||
private ISysSettingsService sysSettingsService; |
|||
|
|||
@BeforeEach |
|||
void setUp() { |
|||
MockitoAnnotations.openMocks(this); |
|||
} |
|||
|
|||
@Test |
|||
void testStartWork() { |
|||
// 1. 准备模拟数据 |
|||
CMDForm form = new CMDForm(); |
|||
form.setCommandId("cmd123"); |
|||
form.setCommandName("startWork"); |
|||
|
|||
Map<String, Object> params = new HashMap<>(); |
|||
params.put("space", 1); |
|||
params.put("routeType", 1); |
|||
params.put("movementSpeed", 100); |
|||
params.put("height", 50); |
|||
params.put("voltage", 100); |
|||
params.put("matrixFlowVelocity", 20); |
|||
params.put("matrixCraftId", 1); |
|||
|
|||
List<Map<String, Integer>> positionList = new ArrayList<>(); |
|||
Map<String, Integer> position = new HashMap<>(); |
|||
position.put("x1", 10); |
|||
position.put("y1", 20); |
|||
position.put("x2", 30); |
|||
position.put("y2", 40); |
|||
position.put("index", 0); |
|||
positionList.add(position); |
|||
params.put("position", positionList); |
|||
|
|||
form.setParams(params); |
|||
|
|||
// 2. 模拟依赖行为 |
|||
SysSettings mockSetting = new SysSettings(); |
|||
mockSetting.setValue("100,200,300"); // 模拟托盘坐标 |
|||
when(sysSettingsService.getSlidePositionList()).thenReturn(Collections.singletonList(mockSetting)); |
|||
|
|||
when(deviceTcpCMDService.switchThreeWayValveToSpray()).thenReturn(true); |
|||
when(deviceTcpCMDService.setMotorSpeed(anyString(), anyInt())).thenReturn(true); |
|||
when(deviceTcpCMDService.moveMotorToPosition(anyString(), anyDouble())).thenReturn(true); |
|||
when(deviceTcpCMDService.turnOnHighVoltage(anyDouble())).thenReturn(true); |
|||
when(deviceTcpCMDService.controlValve(anyString(), anyBoolean())).thenReturn(true); |
|||
when(deviceTcpCMDService.syringePumpMoveAtSpeed(anyInt())).thenReturn(true); |
|||
when(deviceTcpCMDService.turnOffSyringePump()).thenReturn(true); |
|||
when(deviceTcpCMDService.motorMoveToHome(anyString())).thenReturn(true); |
|||
|
|||
// OperationLog mockLog = new OperationLog(); |
|||
// when(operationLogService.getIng()).thenReturn(mockLog); |
|||
// when(operationLogService.add(any())).thenReturn(true); |
|||
// when(operationLogService.updateById(any())).thenReturn(true); |
|||
|
|||
// 3. 调用测试方法 |
|||
String result = cmdService.startWork(form); |
|||
|
|||
// 4. 验证 |
|||
verify(deviceTcpCMDService, times(1)).switchThreeWayValveToSpray(); |
|||
verify(deviceTcpCMDService, times(1)).setMotorSpeed("x", 100); |
|||
verify(deviceTcpCMDService, times(1)).setMotorSpeed("y", 100); |
|||
verify(deviceTcpCMDService, times(1)).setMotorSpeed("z", 100); |
|||
verify(deviceTcpCMDService, times(1)).moveMotorToPosition("z", 350); // z + height (300+50) |
|||
verify(deviceTcpCMDService, times(1)).moveMotorToPosition("x", 110); // x+10 |
|||
verify(deviceTcpCMDService, times(1)).moveMotorToPosition("y", 220); // y+20 |
|||
verify(deviceTcpCMDService, times(1)).turnOnHighVoltage(100); |
|||
|
|||
// 日志校验 |
|||
// verify(operationLogService, times(1)).add(any(OperationLog.class)); |
|||
// verify(operationLogService, times(1)).updateById(any(OperationLog.class)); |
|||
|
|||
// 轨迹移动和其他控制指令同理,这里可以补充更多verify |
|||
|
|||
verify(deviceTcpCMDService, atLeastOnce()).moveMotorToPosition(eq("x"), anyDouble()); |
|||
verify(deviceTcpCMDService, atLeastOnce()).moveMotorToPosition(eq("y"), anyDouble()); |
|||
|
|||
|
|||
// 6. 说明 |
|||
System.out.println("✅ startWork测试通过!"); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue