OCT REM: 1. 优化单元测试执行速度
This commit is contained in:
parent
9a28f38e47
commit
169d2e8fa3
|
@ -1,14 +1,16 @@
|
|||
package com.cmcc.magent.misc;
|
||||
|
||||
import com.cmcc.magent.common.ErrorCode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.groups.Default;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -26,6 +28,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
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.anyString;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
|
@ -49,7 +53,6 @@ import static org.mockito.Mockito.when;
|
|||
* @version 1.0.0
|
||||
* @since 2025-01-14
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
@DisplayName("辅助功能函数")
|
||||
public class HelperUtilsTest {
|
||||
|
@ -60,28 +63,17 @@ public class HelperUtilsTest {
|
|||
@Mock
|
||||
private Validator validator;
|
||||
|
||||
/**
|
||||
* 测试 JSON 序列化功能。
|
||||
* <p>
|
||||
* 验证 {@link JsonUtils#getJson(Object)} 方法是否能正确序列化传入的对象为 JSON 字符串。
|
||||
* </p>
|
||||
*
|
||||
* @throws Exception 如果 JSON 序列化失败
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("JSON 序列化")
|
||||
void testGetJson() throws Exception {
|
||||
// 创建一个测试对象
|
||||
Long jsonVal = 123L;
|
||||
|
||||
// 调用 getJson 方法
|
||||
String json = JsonUtils.getJson(jsonVal);
|
||||
|
||||
// 断言生成的 JSON 字符串不为空
|
||||
assertNotNull(json);
|
||||
assertEquals(new ObjectMapper().writeValueAsString(jsonVal), json);
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试字符串截断功能。
|
||||
* <p>
|
||||
|
@ -108,6 +100,24 @@ public class HelperUtilsTest {
|
|||
assertTrue(truncatedString.startsWith(orgString.substring(0, maxLength - 3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("字符串截断-长度小于等于最大长度")
|
||||
void testTruncateString_NotNeedRun() {
|
||||
// 原始字符串
|
||||
String orgString = "This is a long string";
|
||||
|
||||
// 截断长度
|
||||
int maxLength = 128;
|
||||
|
||||
// 调用 truncateString 方法
|
||||
String truncatedString = HelperUtils.truncateString(orgString, maxLength);
|
||||
|
||||
log.info("[{}] --> [{}]", orgString, truncatedString);
|
||||
// 断言截断后的字符串长度符合预期
|
||||
assertEquals(orgString.length(), truncatedString.length());
|
||||
assertEquals(orgString, truncatedString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试字节数组转换为十六进制字符串功能。
|
||||
* <p>
|
||||
|
@ -278,24 +288,39 @@ public class HelperUtilsTest {
|
|||
@Test
|
||||
@DisplayName("参数校验")
|
||||
public void validate_ValidObject_NoViolations() {
|
||||
Object validObject = new Object(); // 假设这是一个有效的对象
|
||||
when(validator.validate(validObject)).thenReturn(Collections.emptySet());
|
||||
try (MockedStatic<ApiContextUtils> apiContextUtilsMocked = mockStatic(ApiContextUtils.class);
|
||||
MockedStatic<SpringBootBeanUtils> springBootBeanUtilsMocked = mockStatic(SpringBootBeanUtils.class)
|
||||
) {
|
||||
apiContextUtilsMocked.when(ApiContextUtils::getLanguage).thenReturn("zh_CN");
|
||||
springBootBeanUtilsMocked.when(() -> SpringBootBeanUtils.getBean(LocalValidatorFactoryBean.class)).thenReturn(validatorFactory);
|
||||
Object validObject = new Object(); // 假设这是一个有效的对象
|
||||
when(validator.validate(validObject)).thenReturn(Collections.emptySet());
|
||||
when(validatorFactory.getValidator()).thenReturn(validator);
|
||||
|
||||
List<String> errors = HelperUtils.validate(validObject);
|
||||
List<String> errors = HelperUtils.validate(validObject);
|
||||
|
||||
assertEquals(Collections.emptyList(), errors);
|
||||
assertEquals(Collections.emptyList(), errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("参数校验空集合")
|
||||
public void validate_ValidObjectWithGroups_NoViolations() {
|
||||
Object validObject = new Object(); // 假设这是一个有效的对象
|
||||
when(validator.validate(validObject, Default.class)).thenReturn(Collections.emptySet());
|
||||
try (MockedStatic<ApiContextUtils> apiContextUtilsMocked = mockStatic(ApiContextUtils.class);
|
||||
MockedStatic<SpringBootBeanUtils> springBootBeanUtilsMocked = mockStatic(SpringBootBeanUtils.class)
|
||||
) {
|
||||
apiContextUtilsMocked.when(ApiContextUtils::getLanguage).thenReturn("zh_CN");
|
||||
springBootBeanUtilsMocked.when(() -> SpringBootBeanUtils.getBean(LocalValidatorFactoryBean.class)).thenReturn(validatorFactory);
|
||||
when(validatorFactory.getValidator()).thenReturn(validator);
|
||||
|
||||
List<String> errors = HelperUtils.validate(validObject, Default.class);
|
||||
Object validObject = new Object(); // 假设这是一个有效的对象
|
||||
when(validator.validate(validObject, Default.class)).thenReturn(Collections.emptySet());
|
||||
|
||||
assertEquals(Collections.emptyList(), errors);
|
||||
List<String> errors = HelperUtils.validate(validObject, Default.class);
|
||||
|
||||
assertEquals(Collections.emptyList(), errors);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -313,12 +338,75 @@ public class HelperUtilsTest {
|
|||
@Test
|
||||
@DisplayName("格式化消息")
|
||||
public void testGetFormatMessage() {
|
||||
List<String> errors = List.of("error1", "error2");
|
||||
String[] result = HelperUtils.formatErrorMessage(ErrorCode.ERR_PARAMEXCEPTION, errors);
|
||||
assertNotNull(result);
|
||||
assertEquals(3, result.length);
|
||||
assertEquals("0: " + ErrorCode.ERR_PARAMEXCEPTION.getDescription(), result[0]);
|
||||
assertEquals("1: error1", result[1]);
|
||||
assertEquals("2: error2", result[2]);
|
||||
try (MockedStatic<MessageUtil> mockedMessageUtil = mockStatic(MessageUtil.class)) {
|
||||
mockedMessageUtil.when(() -> MessageUtil.get(anyString(), anyString())).thenReturn("Error message");
|
||||
List<String> errors = List.of("error1", "error2");
|
||||
String[] result = HelperUtils.formatErrorMessage(ErrorCode.ERR_PARAMEXCEPTION, errors);
|
||||
assertNotNull(result);
|
||||
assertEquals(3, result.length);
|
||||
assertEquals("0: " + ErrorCode.ERR_PARAMEXCEPTION.getDescription(), result[0]);
|
||||
assertEquals("1: error1", result[1]);
|
||||
assertEquals("2: error2", result[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getField-获取私有字段值")
|
||||
public void getField_ValidInput_ReturnsFieldValue() throws Exception {
|
||||
// 准备测试对象
|
||||
TestObject testObj = new TestObject("testValue");
|
||||
|
||||
// 获取私有字段值
|
||||
String fieldValue = HelperUtils.getField(testObj, "field");
|
||||
|
||||
// 验证
|
||||
assertEquals("testValue", fieldValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getField-字段不存在抛出异常")
|
||||
public void getField_NonExistingField_ThrowsException() {
|
||||
TestObject testObj = new TestObject("testValue");
|
||||
|
||||
assertThrows(NoSuchFieldException.class, () -> {
|
||||
HelperUtils.getField(testObj, "nonExistingField");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("setField-设置私有字段值")
|
||||
public void setField_ValidInput_SetsFieldValue() throws Exception {
|
||||
// 准备测试对象
|
||||
TestObject testObj = new TestObject("oldValue");
|
||||
|
||||
// 设置私有字段值
|
||||
HelperUtils.setField(testObj, "field", "newValue");
|
||||
|
||||
// 验证字段值已更新
|
||||
assertEquals("newValue", testObj.getField());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("setField-字段不存在抛出异常")
|
||||
public void setField_NonExistingField_ThrowsException() {
|
||||
TestObject testObj = new TestObject("testValue");
|
||||
|
||||
assertThrows(NoSuchFieldException.class, () -> {
|
||||
HelperUtils.setField(testObj, "nonExistingField", "newValue");
|
||||
});
|
||||
}
|
||||
|
||||
// 测试用内部类
|
||||
private static class TestObject {
|
||||
private String field;
|
||||
|
||||
public TestObject(String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
// 用于验证字段值是否被正确设置
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
package com.cmcc.magent.misc;
|
||||
|
||||
import com.cmcc.magent.config.ObjectMapperProvider;
|
||||
import com.cmcc.magent.pojo.po.BaseRespStatus;
|
||||
import com.cmcc.magent.pojo.po.MemoryDetails;
|
||||
import com.cmcc.magent.pojo.vo.BasePageResultResp;
|
||||
import com.cmcc.magent.pojo.vo.ProtocolResp;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import jakarta.servlet.ReadListener;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -22,11 +26,15 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
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.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* 测试类:ProtocolJsonUtils 测试
|
||||
|
@ -46,365 +54,35 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
* @version 1.0.0
|
||||
* @since 2025-01-20
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
@DisplayName("ProtocolJsonUtils 测试类")
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ProtocolJsonUtilsTest {
|
||||
private static final ObjectMapper mockObjectMapper = new ObjectMapper();
|
||||
private static MockedStatic<ObjectMapperProvider> objectMapperProviderMock;
|
||||
private TestObject testObj;
|
||||
private ServletInputStream servletInputStream;
|
||||
|
||||
private ProtocolResp protocolResp;
|
||||
private ProtocolResp protocolRespB;
|
||||
private ServletInputStream servletInputStream;
|
||||
private String validJson;
|
||||
private String invalidJson;
|
||||
private String validJsonB;
|
||||
private String invalidJsonB;
|
||||
private String emptyJson;
|
||||
private String validJsonB2;
|
||||
private String invalidJsonB2;
|
||||
@BeforeAll
|
||||
public static void setUpAll() {
|
||||
objectMapperProviderMock = mockStatic(ObjectMapperProvider.class);
|
||||
objectMapperProviderMock.when(ObjectMapperProvider::getMapper).thenReturn(mockObjectMapper);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void tearDownAll() {
|
||||
objectMapperProviderMock.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化方法:在每个测试方法执行之前运行。
|
||||
*
|
||||
* <p>此方法初始化需要的测试数据。</p>
|
||||
*/
|
||||
@BeforeEach
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
protocolResp = new ProtocolResp();
|
||||
protocolRespB = new ProtocolResp();
|
||||
protocolRespB.setVer(1);
|
||||
protocolRespB.setCryptoType(1);
|
||||
protocolRespB.setTimeStamp(12345L);
|
||||
protocolRespB.setCode(200);
|
||||
protocolRespB.setMsgContent(new String[] {"Test Protocol"});
|
||||
public void setUp() throws IOException {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
|
||||
servletInputStream = Mockito.mock(ServletInputStream.class);
|
||||
testObj = new TestObject("testValue");
|
||||
|
||||
validJson = "{\"code\":\"0000\",\"msg\":\"success\",\"data\":{\"id\":\"12345\",\"name\":\"Test Name\"}}";
|
||||
invalidJson = "{\"code\":\"0000\",\"msg\":\"success\",\"data\":{}}"; // 缺少字段
|
||||
|
||||
validJsonB = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1633072800000,\"code\":200,\"msgContent\":{\"status\":0," +
|
||||
"\"message\":[\"操作成功\"]}}";
|
||||
invalidJsonB = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1633072800000,\"code\":200,\"msgContent\":\"Invalid content\"}";
|
||||
emptyJson = "";
|
||||
|
||||
validJsonB2 = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1672531200000,\"code\":200,\"msgContent\":{\"status\":0," +
|
||||
"\"message\":[\"操作成功\"]}}";
|
||||
invalidJsonB2 = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1672531200000,\"code\":200,\"msgContent\":{\"status\":0}}"; // 缺少
|
||||
// message 字段
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于有效对象,getJsonBytes 方法应返回 JSON 字节数组。
|
||||
*
|
||||
* <p>预期结果:返回非空的 JSON 字节数组,包含对象的各个字段。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("有效对象应返回 JSON 字节数组")
|
||||
public void getJsonBytes_ValidObject_ShouldReturnJsonBytes() throws JsonProcessingException {
|
||||
byte[] jsonBytes = ProtocolJsonUtils.getJsonBytes(protocolRespB, StandardCharsets.UTF_8);
|
||||
assertNotNull(jsonBytes);
|
||||
assertTrue(jsonBytes.length > 0);
|
||||
String jsonString = new String(jsonBytes, StandardCharsets.UTF_8);
|
||||
assertTrue(jsonString.contains("ver"));
|
||||
assertTrue(jsonString.contains("cryptoType"));
|
||||
assertTrue(jsonString.contains("timeStamp"));
|
||||
assertTrue(jsonString.contains("code"));
|
||||
assertTrue(jsonString.contains("msgContent"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于空对象,getJsonBytes 方法应返回空字节数组。
|
||||
*
|
||||
* <p>预期结果:返回表示 "null" 的字节数组。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("空对象应返回空字节数组")
|
||||
public void getJsonBytes_NullObject_ShouldReturnEmptyByteArray() throws JsonProcessingException {
|
||||
byte[] jsonBytes = ProtocolJsonUtils.getJsonBytes(null, StandardCharsets.UTF_8);
|
||||
assertNotNull(jsonBytes);
|
||||
assertEquals(4, jsonBytes.length);
|
||||
assertEquals("null", new String(jsonBytes, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:使用不同字符集时,getJsonBytes 方法应返回指定字符集的 JSON 字节数组。
|
||||
*
|
||||
* <p>预期结果:返回的 JSON 字节数组使用指定的字符集编码。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("不同字符集应返回指定字符集的 JSON 字节数组")
|
||||
public void getJsonBytes_DifferentCharset_ShouldReturnJsonBytesInSpecifiedCharset() throws JsonProcessingException {
|
||||
byte[] jsonBytes = ProtocolJsonUtils.getJsonBytes(protocolRespB, StandardCharsets.UTF_8);
|
||||
assertNotNull(jsonBytes);
|
||||
assertTrue(jsonBytes.length > 0);
|
||||
String jsonString = new String(jsonBytes, StandardCharsets.UTF_8);
|
||||
assertTrue(jsonString.contains("ver"));
|
||||
assertTrue(jsonString.contains("cryptoType"));
|
||||
assertTrue(jsonString.contains("timeStamp"));
|
||||
assertTrue(jsonString.contains("code"));
|
||||
assertTrue(jsonString.contains("msgContent"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于空 JSON 字符串,jsonGetObject 方法应抛出异常。
|
||||
*
|
||||
* <p>预期结果:抛出 {@link JsonProcessingException}。</p>
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("空 JSON 应抛出异常")
|
||||
public void jsonGetObject_EmptyJson_ThrowsException() {
|
||||
String emptyJson = "";
|
||||
assertThrows(JsonProcessingException.class, () -> ProtocolJsonUtils.jsonGetObject(emptyJson, ProtocolResp.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于不匹配的 JSON 字符串,jsonGetObject 方法应返回默认对象。
|
||||
*
|
||||
* <p>预期结果:返回的对象字段为 null。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("不匹配的 JSON 应返回默认对象")
|
||||
@SuppressWarnings("unchecked")
|
||||
public void jsonGetObject_MismatchedJson() throws JsonProcessingException {
|
||||
String mismatchedJson = "{\"protocolId\":12345,\"protocolName\":true,\"protocolType\":null,\"protocolVersion\":1.0," +
|
||||
"\"protocolStatus\":\"SUCCESS\"}";
|
||||
|
||||
ProtocolResp<String> actualProtocolResp = ProtocolJsonUtils.jsonGetObject(mismatchedJson, ProtocolResp.class);
|
||||
assertNull(actualProtocolResp.getVer());
|
||||
assertNull(actualProtocolResp.getCryptoType());
|
||||
assertNull(actualProtocolResp.getTimeStamp());
|
||||
assertNull(actualProtocolResp.getCode());
|
||||
assertNull(actualProtocolResp.getMsgContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于无效 JSON 字符串,jsonGetObject 方法应抛出 IOException。
|
||||
*
|
||||
* <p>预期结果:抛出 {@link IOException}。</p>
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("无效 JSON 应抛出 IOException")
|
||||
public void jsonGetObject_InvalidJson_ThrowsIOException() {
|
||||
String invalidJson = "{\"code\":\"0000\",\"message\":\"success\",\"data\":{\"id\":\"12345678901234567890123456789012\"," +
|
||||
"\"name\":\"test\",\"status\":\"1\",\"remark\":\"remark\"}";
|
||||
InputStream inputStream = new ByteArrayInputStream(invalidJson.getBytes());
|
||||
servletInputStream = new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
assertThrows(IOException.class, () -> ProtocolJsonUtils.jsonGetObject(servletInputStream, new TypeReference<ProtocolResp>() {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于空 JSON 对象,jsonGetObject 方法应返回默认对象。
|
||||
*
|
||||
* <p>预期结果:返回的对象与默认对象相同。</p>
|
||||
*
|
||||
* @throws IOException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("空 JSON 对象应返回默认对象")
|
||||
public void jsonGetObject_EmptyJsonObject_ReturnsDefaultObject() throws IOException {
|
||||
String json = "{}";
|
||||
InputStream inputStream = new ByteArrayInputStream(json.getBytes());
|
||||
servletInputStream = new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
ProtocolResp result = ProtocolJsonUtils.jsonGetObject(servletInputStream, new TypeReference<>() {
|
||||
});
|
||||
|
||||
assertEquals(new ProtocolResp(), result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于有效 JSONB 字符串,jsonGetObject 方法应返回 ProtocolResp。
|
||||
*
|
||||
* <p>预期结果:返回的对象包含正确的字段值。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("有效 JSONB 应返回 ProtocolResp")
|
||||
public void jsonGetObject_ValidJsonB_ShouldReturnProtocolResp() throws JsonProcessingException {
|
||||
String json = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1737339486666,\"code\":200,\"msgContent\":{\"items\":{\"pageNumber\":1," +
|
||||
"\"pageSize\":10,\"totalPage\":1,\"totalRow\":2,\"items\":[{\"totalMemory\":326236233336,\"freeMemory\":132532643}," +
|
||||
"{\"totalMemory\":2326236233336,\"freeMemory\":2132532643}]},\"status\":0,\"message\":[\"Successful\"]}}";
|
||||
|
||||
ProtocolResp<?> resp = ProtocolJsonUtils.jsonGetProtocolResp(json, new Class<?>[] {BasePageResultResp.class, MemoryDetails.class});
|
||||
assertNotNull(resp);
|
||||
assertEquals(200, resp.getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于有效 JSON 字符串,jsonGetObject 方法应成功反序列化。
|
||||
*
|
||||
* <p>预期结果:返回的对象不为空,并包含正确的数据。</p>
|
||||
*
|
||||
* @throws IOException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("有效 JSON 成功反序列化")
|
||||
public void jsonGetObject_ValidJson_SuccessfulDeserialization() throws IOException {
|
||||
ProtocolResp<?> result = ProtocolJsonUtils.jsonGetObject(validJson, new TypeReference<>() {
|
||||
});
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于空 JSON 字符串,jsonGetObject 方法应抛出 IOException。
|
||||
*
|
||||
* <p>预期结果:抛出 {@link IOException}。</p>
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("空 JSON 字符串应抛出 IOException")
|
||||
public void jsonGetObject_EmptyJsonString_ThrowsIOException() {
|
||||
assertThrows(IOException.class, () -> ProtocolJsonUtils.jsonGetObject("", new TypeReference<ProtocolResp<?>>() {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于有效 JSON 字符串,jsonGetProtocolResp 方法应成功反序列化。
|
||||
*
|
||||
* <p>预期结果:返回的对象包含正确的字段值。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("有效 JSON 成功反序列化")
|
||||
public void jsonGetProtocolResp_ValidJson_SuccessfulDeserialization() throws JsonProcessingException {
|
||||
ProtocolResp<? extends BaseRespStatus> protocolResp = ProtocolJsonUtils.jsonGetProtocolResp(validJsonB, BaseRespStatus.class);
|
||||
assertNotNull(protocolResp);
|
||||
assertEquals(1, protocolResp.getVer());
|
||||
assertEquals(0, protocolResp.getCryptoType());
|
||||
assertEquals(200, protocolResp.getCode());
|
||||
assertNotNull(protocolResp.getMsgContent());
|
||||
assertEquals(0, protocolResp.getMsgContent().getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于无效 JSON 字符串,jsonGetProtocolResp 方法应抛出 JsonProcessingException。
|
||||
*
|
||||
* <p>预期结果:抛出 {@link JsonProcessingException}。</p>
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("无效 JSON 应抛出 JsonProcessingException")
|
||||
public void jsonGetProtocolResp_InvalidJson_ThrowsJsonProcessingException() {
|
||||
assertThrows(JsonProcessingException.class, () -> ProtocolJsonUtils.jsonGetProtocolResp(invalidJsonB, BaseRespStatus.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于空 JSON 字符串,jsonGetProtocolResp 方法应抛出 JsonProcessingException。
|
||||
*
|
||||
* <p>预期结果:抛出 {@link JsonProcessingException}。</p>
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("空 JSON 应抛出 JsonProcessingException")
|
||||
public void jsonGetProtocolResp_EmptyJson_ThrowsJsonProcessingException() {
|
||||
assertThrows(JsonProcessingException.class, () -> ProtocolJsonUtils.jsonGetProtocolResp(emptyJson, BaseRespStatus.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于有效 JSON 字符串,jsonGetProtocolResp 方法应返回 ProtocolResp。
|
||||
*
|
||||
* <p>预期结果:返回的对象包含正确的字段值。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("有效 JSON 应返回 ProtocolResp")
|
||||
public void jsonGetProtocolResp_ValidJson_ShouldReturnProtocolResp() throws JsonProcessingException {
|
||||
ProtocolResp<? extends BaseRespStatus> result = ProtocolJsonUtils.jsonGetProtocolResp(validJsonB2,
|
||||
new Class<?>[] {BaseRespStatus.class});
|
||||
assertEquals(1, result.getVer());
|
||||
assertEquals(0, result.getCryptoType());
|
||||
assertEquals(1672531200000L, result.getTimeStamp());
|
||||
assertEquals(200, result.getCode());
|
||||
assertEquals(0, result.getMsgContent().getStatus());
|
||||
assertEquals("操作成功", result.getMsgContent().getMessage()[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:对于嵌套泛型的 JSON 字符串,jsonGetProtocolResp 方法应正确处理。
|
||||
*
|
||||
* <p>预期结果:返回的对象中的消息字段包含多个条目。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果反序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("嵌套泛型应正确处理")
|
||||
public void jsonGetProtocolResp_NestedGenerics_ShouldHandleCorrectly() throws JsonProcessingException {
|
||||
String nestedJson = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":1672531200000,\"code\":200," +
|
||||
"\"msgContent\":{\"status\":0,\"message\":[\"操作成功\",\"另一个消息\"]}}";
|
||||
ProtocolResp<? extends BaseRespStatus> result = ProtocolJsonUtils.jsonGetProtocolResp(nestedJson,
|
||||
new Class<?>[] {BaseRespStatus.class});
|
||||
assertEquals(2, result.getMsgContent().getMessage().length);
|
||||
assertEquals("另一个消息", result.getMsgContent().getMessage()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试场景:getJsonBytes 方法应成功返回对象的 JSON 字节数组。
|
||||
*
|
||||
* <p>预期结果:返回的字节数组不为空。</p>
|
||||
*
|
||||
* @throws JsonProcessingException 如果序列化过程中发生错误
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("getJsonBytes 应成功")
|
||||
public void jsonGetProtocolResp_GetJsonBytes_ShouldSuccessfully() throws JsonProcessingException {
|
||||
MemoryDetails memoryDetails = new MemoryDetails();
|
||||
memoryDetails.setTotalMemory(1234567890L);
|
||||
memoryDetails.setFreeMemory(987654321L);
|
||||
|
||||
byte[] ret = ProtocolJsonUtils.getJsonBytes(memoryDetails);
|
||||
assertNotEquals(0, ret.length);
|
||||
// 模拟ServletInputStream
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream("{\"field\":\"testValue\"}".getBytes(StandardCharsets.UTF_8));
|
||||
servletInputStream = mock(ServletInputStream.class);
|
||||
when(servletInputStream.read()).thenAnswer(invocation -> inputStream.read());
|
||||
}
|
||||
|
||||
|
||||
|
@ -414,8 +92,170 @@ public class ProtocolJsonUtilsTest {
|
|||
assertThrows(InvocationTargetException.class, () -> {
|
||||
Constructor<ProtocolJsonUtils> constructor = ProtocolJsonUtils.class.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
ProtocolJsonUtils instance = constructor.newInstance();
|
||||
assertNotNull(instance);
|
||||
constructor.newInstance();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("对象序列化为字节数组")
|
||||
public void getJsonBytes_ValidObject_ReturnsBytes() throws JsonProcessingException {
|
||||
byte[] result = ProtocolJsonUtils.getJsonBytes(testObj);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("指定字符集序列化")
|
||||
public void getJsonBytes_WithCharset_ReturnsBytes() throws JsonProcessingException {
|
||||
byte[] result = ProtocolJsonUtils.getJsonBytes(testObj, StandardCharsets.UTF_8);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("从字符串反序列化")
|
||||
public void jsonGetObject_FromString_ReturnsObject() throws JsonProcessingException {
|
||||
String json = "{\"field\":\"testValue\"}";
|
||||
TestObject result = ProtocolJsonUtils.jsonGetObject(json, TestObject.class);
|
||||
assertEquals("testValue", result.field());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("从输入流反序列化")
|
||||
public void jsonGetObject_FromInputStream_ReturnsObject() throws IOException {
|
||||
String json = "{\"field\":\"testValue\"}";
|
||||
TypeReference<TestObject> typeReference = new TypeReference<>() {
|
||||
};
|
||||
|
||||
try (MockedStatic<HelperUtils> helperUtilsMock = mockStatic(HelperUtils.class)
|
||||
) {
|
||||
helperUtilsMock.when(() -> HelperUtils.inputStream2String(any(InputStream.class))).thenReturn(json);
|
||||
TestObject result = ProtocolJsonUtils.jsonGetObject(servletInputStream, typeReference);
|
||||
assertEquals("testValue", result.field());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("从字符串反序列化(TypeReference)")
|
||||
public void jsonGetObject_FromStringWithType_ReturnsObject() throws IOException {
|
||||
String json = "{\"field\":\"testValue\"}";
|
||||
TypeReference<TestObject> typeReference = new TypeReference<>() {
|
||||
};
|
||||
|
||||
TestObject result = ProtocolJsonUtils.jsonGetObject(json, typeReference);
|
||||
assertEquals("testValue", result.field());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("基本类型反序列化")
|
||||
public void jsonGetProtocolResp_SimpleType_ReturnsProtocolResp() throws JsonProcessingException {
|
||||
String json = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":12345,\"code\":200,\"msgContent\":{\"status\":0,\"message\":[\"成功\"]}}";
|
||||
|
||||
try (MockedStatic<MessageUtil> messageUtilMock = mockStatic(MessageUtil.class)) {
|
||||
messageUtilMock.when(() -> MessageUtil.get(anyString(), anyString())).thenReturn("成功");
|
||||
BaseRespStatus status = new BaseRespStatus(0, new String[] {"成功"});
|
||||
ProtocolResp<BaseRespStatus> resp = new ProtocolResp<>();
|
||||
resp.setVer(1);
|
||||
resp.setCryptoType(0);
|
||||
resp.setTimeStamp(12345L);
|
||||
resp.setCode(200);
|
||||
resp.setMsgContent(status);
|
||||
|
||||
ProtocolResp<? extends BaseRespStatus> result = ProtocolJsonUtils.jsonGetProtocolResp(json, BaseRespStatus.class);
|
||||
assertEquals(200, result.getCode());
|
||||
assertEquals(0, result.getMsgContent().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("嵌套泛型反序列化")
|
||||
public void jsonGetProtocolResp_NestedGenerics_ReturnsProtocolResp() throws JsonProcessingException {
|
||||
String json = "{\"ver\":1,\"cryptoType\":0,\"timeStamp\":12345,\"code\":200,\"msgContent\":{\"status\":0,\"message\":[\"成功\"]}}";
|
||||
|
||||
try (MockedStatic<MessageUtil> messageUtilMock = mockStatic(MessageUtil.class)) {
|
||||
messageUtilMock.when(() -> MessageUtil.get(anyString(), anyString())).thenReturn("成功");
|
||||
BaseRespStatus status = new BaseRespStatus(0, new String[] {"成功"});
|
||||
ProtocolResp<BaseRespStatus> resp = new ProtocolResp<>();
|
||||
resp.setVer(1);
|
||||
resp.setCryptoType(0);
|
||||
resp.setTimeStamp(12345L);
|
||||
resp.setCode(200);
|
||||
resp.setMsgContent(status);
|
||||
|
||||
ProtocolResp<? extends BaseRespStatus> result = ProtocolJsonUtils.jsonGetProtocolResp(json,
|
||||
new Class<?>[] {BaseRespStatus.class});
|
||||
assertEquals(200, result.getCode());
|
||||
assertEquals(0, result.getMsgContent().getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("无效JSON抛出异常")
|
||||
public void jsonGetObject_InvalidJson_ThrowsException() {
|
||||
String invalidJson = "{invalid json}";
|
||||
assertThrows(JsonProcessingException.class, () -> {
|
||||
ProtocolJsonUtils.jsonGetObject(invalidJson, TestObject.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("从字符串反序列化(TypeReference嵌套)")
|
||||
void jsonGetProtocolResp_shouldHandleTreeLevelNesting() throws Exception {
|
||||
try (MockedStatic<MessageUtil> messageUtilMock = mockStatic(MessageUtil.class)) {
|
||||
messageUtilMock.when(() -> MessageUtil.get(anyString(), anyString())).thenReturn("testMessage");
|
||||
// 准备测试数据(三层嵌套)
|
||||
|
||||
Class<?>[] classes = {NestedResp.class, TestStatus.class, LastStatus.class};
|
||||
|
||||
LastStatus lastStatus = new LastStatus();
|
||||
lastStatus.setStatus(0);
|
||||
lastStatus.setMessage(new String[] {"LastStatus"});
|
||||
|
||||
TestStatus<LastStatus> testStatus = new TestStatus<>();
|
||||
testStatus.setStatus(1);
|
||||
testStatus.setMessage(new String[] {"TestStatus"});
|
||||
testStatus.setData(lastStatus);
|
||||
|
||||
NestedResp<TestStatus<LastStatus>> nestedResp = new NestedResp<>();
|
||||
nestedResp.setStatus(2);
|
||||
nestedResp.setMessage(new String[] {"NestedResp"});
|
||||
nestedResp.setData(testStatus);
|
||||
|
||||
ProtocolResp<NestedResp<TestStatus<LastStatus>>> ret = new ProtocolResp<>();
|
||||
ret.setVer(1);
|
||||
ret.setCryptoType(0);
|
||||
ret.setTimeStamp(12345L);
|
||||
ret.setCode(200);
|
||||
ret.setMsgContent(nestedResp);
|
||||
String objJson = mockObjectMapper.writeValueAsString(ret);
|
||||
log.info("++++{}: {}", mockObjectMapper.hashCode(), objJson);
|
||||
|
||||
// 执行方法
|
||||
ProtocolResp<? extends BaseRespStatus> result = ProtocolJsonUtils.jsonGetProtocolResp(objJson, classes);
|
||||
|
||||
// 验证嵌套结构
|
||||
assertInstanceOf(NestedResp.class, result.getMsgContent());
|
||||
NestedResp<?> nested = (NestedResp<?>) result.getMsgContent();
|
||||
assertEquals(TestStatus.class, nested.getData().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// 测试用内部类
|
||||
private record TestObject(String field) {
|
||||
}
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private static class NestedResp<T> extends BaseRespStatus {
|
||||
private T data;
|
||||
}
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
static class TestStatus<T> extends BaseRespStatus {
|
||||
private T data;
|
||||
}
|
||||
|
||||
static class LastStatus extends BaseRespStatus {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue