新增e2e测试脚本,修复部分问题

This commit was merged in pull request #51.
This commit is contained in:
2026-07-22 20:00:13 +08:00
parent 53d1ce6fb2
commit 4c07ec5455
105 changed files with 21700 additions and 318 deletions
@@ -0,0 +1,99 @@
package cn.novalon.gym.manage.common.dto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("PageRequest 单元测试")
class PageRequestTest {
@Test
@DisplayName("无参构造应使用默认值:page=0, size=10, sort='id', order='asc'")
void defaultConstructorShouldUseDefaults() {
PageRequest pr = new PageRequest();
assertThat(pr.getPage()).isEqualTo(0);
assertThat(pr.getSize()).isEqualTo(10);
assertThat(pr.getSort()).isEqualTo("id");
assertThat(pr.getOrder()).isEqualTo("asc");
}
@Test
@DisplayName("setter和getter应正确设置和读取page")
void shouldSetAndGetPage() {
PageRequest pr = new PageRequest();
pr.setPage(2);
assertThat(pr.getPage()).isEqualTo(2);
}
@Test
@DisplayName("setter和getter应正确设置和读取size")
void shouldSetAndGetSize() {
PageRequest pr = new PageRequest();
pr.setSize(50);
assertThat(pr.getSize()).isEqualTo(50);
}
@Test
@DisplayName("setter和getter应正确设置和读取sort")
void shouldSetAndGetSort() {
PageRequest pr = new PageRequest();
pr.setSort("createTime");
assertThat(pr.getSort()).isEqualTo("createTime");
}
@Test
@DisplayName("setter和getter应正确设置和读取order")
void shouldSetAndGetOrder() {
PageRequest pr = new PageRequest();
pr.setOrder("desc");
assertThat(pr.getOrder()).isEqualTo("desc");
}
@Test
@DisplayName("setter和getter应正确设置和读取keyword")
void shouldSetAndGetKeyword() {
PageRequest pr = new PageRequest();
pr.setKeyword("搜索关键词");
assertThat(pr.getKeyword()).isEqualTo("搜索关键词");
}
@Test
@DisplayName("setter和getter应正确设置和读取status")
void shouldSetAndGetStatus() {
PageRequest pr = new PageRequest();
pr.setStatus("ACTIVE");
assertThat(pr.getStatus()).isEqualTo("ACTIVE");
}
@Test
@DisplayName("setter和getter应正确设置和读取category")
void shouldSetAndGetCategory() {
PageRequest pr = new PageRequest();
pr.setCategory("GROUP_COURSE");
assertThat(pr.getCategory()).isEqualTo("GROUP_COURSE");
}
@Test
@DisplayName("所有字段应可正常设置和读取")
void shouldSetAndGetAllFieldsCorrectly() {
PageRequest pr = new PageRequest();
pr.setPage(1);
pr.setSize(25);
pr.setSort("name");
pr.setOrder("desc");
pr.setKeyword("test");
pr.setStatus("INACTIVE");
pr.setCategory("PRIVATE");
assertThat(pr.getPage()).isEqualTo(1);
assertThat(pr.getSize()).isEqualTo(25);
assertThat(pr.getSort()).isEqualTo("name");
assertThat(pr.getOrder()).isEqualTo("desc");
assertThat(pr.getKeyword()).isEqualTo("test");
assertThat(pr.getStatus()).isEqualTo("INACTIVE");
assertThat(pr.getCategory()).isEqualTo("PRIVATE");
}
}
@@ -0,0 +1,235 @@
package cn.novalon.gym.manage.common.exception;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("异常类单元测试")
class ExceptionTests {
@Nested
@DisplayName("BusinessException 测试")
class BusinessExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithErrorCodeAndMessage() {
BusinessException ex = new BusinessException(
ErrorCode.VALIDATION_REQUIRED, "参数错误");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.VALIDATION_REQUIRED);
assertThat(ex.getMessage()).isEqualTo("参数错误");
assertThat(ex.getContext()).isEmpty();
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("root cause");
BusinessException ex = new BusinessException(
ErrorCode.VALIDATION_INVALID_VALUE, "值无效", cause);
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.VALIDATION_INVALID_VALUE);
assertThat(ex.getMessage()).isEqualTo("值无效");
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回BAD_REQUEST")
void shouldReturnBadRequest() {
BusinessException ex = new BusinessException("E001", "error");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
}
@Test
@DisplayName("addContext应链式添加上下文并返回自身")
void addContextShouldChainAndAddToContext() {
BusinessException ex = new BusinessException("E001", "error");
BaseException returned = ex.addContext("key1", "value1");
ex.addContext("key2", 123);
assertThat(returned).isSameAs(ex);
assertThat(ex.getContext()).containsEntry("key1", "value1");
assertThat(ex.getContext()).containsEntry("key2", 123);
}
}
@Nested
@DisplayName("NotFoundException 测试")
class NotFoundExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithMessage() {
NotFoundException ex = new NotFoundException(
ErrorCode.NOT_FOUND_USER, "用户不存在");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND_USER);
assertThat(ex.getMessage()).isEqualTo("用户不存在");
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("db error");
NotFoundException ex = new NotFoundException(
ErrorCode.NOT_FOUND_ROLE, "角色不存在", cause);
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND_ROLE);
assertThat(ex.getMessage()).isEqualTo("角色不存在");
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回NOT_FOUND")
void shouldReturnNotFound() {
NotFoundException ex = new NotFoundException("E404", "not found");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.NOT_FOUND);
}
@Test
@DisplayName("应继承自BusinessException")
void shouldExtendBusinessException() {
NotFoundException ex = new NotFoundException("E404", "not found");
assertThat(ex).isInstanceOf(BusinessException.class);
}
}
@Nested
@DisplayName("ValidationException 测试")
class ValidationExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithMessage() {
ValidationException ex = new ValidationException(
ErrorCode.VALIDATION_REQUIRED, "字段不能为空");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.VALIDATION_REQUIRED);
assertThat(ex.getMessage()).isEqualTo("字段不能为空");
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("parse error");
ValidationException ex = new ValidationException(
ErrorCode.VALIDATION_INVALID_FORMAT, "格式错误", cause);
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回BAD_REQUEST")
void shouldReturnBadRequest() {
ValidationException ex = new ValidationException("E001", "error");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
}
}
@Nested
@DisplayName("PermissionException 测试")
class PermissionExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithMessage() {
PermissionException ex = new PermissionException(
ErrorCode.PERMISSION_DENIED, "权限不足");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.PERMISSION_DENIED);
assertThat(ex.getMessage()).isEqualTo("权限不足");
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("auth error");
PermissionException ex = new PermissionException(
ErrorCode.PERMISSION_INSUFFICIENT, "权限不足", cause);
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回FORBIDDEN")
void shouldReturnForbidden() {
PermissionException ex = new PermissionException("E403", "forbidden");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.FORBIDDEN);
}
}
@Nested
@DisplayName("SystemException 测试")
class SystemExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithMessage() {
SystemException ex = new SystemException(
ErrorCode.SYSTEM_INTERNAL_ERROR, "系统内部错误");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.SYSTEM_INTERNAL_ERROR);
assertThat(ex.getMessage()).isEqualTo("系统内部错误");
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("NPE");
SystemException ex = new SystemException(
ErrorCode.SYSTEM_DATABASE_ERROR, "数据库错误", cause);
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回INTERNAL_SERVER_ERROR")
void shouldReturnInternalServerError() {
SystemException ex = new SystemException("E500", "error");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
}
@Test
@DisplayName("应直接继承自BaseException")
void shouldExtendBaseException() {
SystemException ex = new SystemException("E500", "error");
assertThat(ex).isInstanceOf(BaseException.class);
}
}
@Nested
@DisplayName("ConflictException 测试")
class ConflictExceptionTest {
@Test
@DisplayName("带message构造应正确设置errorCode和message")
void shouldConstructWithMessage() {
ConflictException ex = new ConflictException(
ErrorCode.CONFLICT_DUPLICATE, "数据重复");
assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.CONFLICT_DUPLICATE);
assertThat(ex.getMessage()).isEqualTo("数据重复");
}
@Test
@DisplayName("带message和cause构造应正确设置字段")
void shouldConstructWithCause() {
RuntimeException cause = new RuntimeException("unique constraint");
ConflictException ex = new ConflictException(
ErrorCode.CONFLICT_DUPLICATE_USER, "用户重复", cause);
assertThat(ex.getCause()).isSameAs(cause);
}
@Test
@DisplayName("getHttpStatus()应返回CONFLICT")
void shouldReturnConflict() {
ConflictException ex = new ConflictException("E409", "conflict");
assertThat(ex.getHttpStatus()).isEqualTo(HttpStatus.CONFLICT);
}
}
}
@@ -0,0 +1,185 @@
package cn.novalon.gym.manage.common.util;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("HtmlEscapeUtil 单元测试")
class HtmlEscapeUtilTest {
@Nested
@DisplayName("escape 方法测试")
class EscapeTest {
@Test
@DisplayName("应转义HTML特殊字符")
void shouldEscapeHtmlSpecialCharacters() {
String input = "<script>alert('xss')</script>";
String result = HtmlEscapeUtil.escape(input);
assertThat(result).doesNotContain("<");
assertThat(result).doesNotContain(">");
assertThat(result).contains("&lt;");
assertThat(result).contains("&gt;");
assertThat(result).contains("&#39;");
}
@Test
@DisplayName("应转义引号字符")
void shouldEscapeQuotes() {
String result = HtmlEscapeUtil.escape("\"test\"");
assertThat(result).contains("&quot;");
}
@Test
@DisplayName("应转义&符号")
void shouldEscapeAmpersand() {
String result = HtmlEscapeUtil.escape("a & b");
assertThat(result).contains("&amp;");
}
@Test
@DisplayName("null输入应返回null")
void nullInputShouldReturnNull() {
assertThat(HtmlEscapeUtil.escape(null)).isNull();
}
@Test
@DisplayName("空字符串输入应返回空字符串")
void emptyInputShouldReturnEmpty() {
assertThat(HtmlEscapeUtil.escape("")).isEmpty();
}
@Test
@DisplayName("无特殊字符的普通文本应原样返回")
void plainTextShouldReturnUnchanged() {
String input = "Hello World";
assertThat(HtmlEscapeUtil.escape(input)).isEqualTo("Hello World");
}
}
@Nested
@DisplayName("unescape 方法测试")
class UnescapeTest {
@Test
@DisplayName("应反转义HTML实体")
void shouldUnescapeHtmlEntities() {
String input = "&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;";
String result = HtmlEscapeUtil.unescape(input);
assertThat(result).isEqualTo("<script>alert('xss')</script>");
}
@Test
@DisplayName("null输入应返回null")
void nullInputShouldReturnNull() {
assertThat(HtmlEscapeUtil.unescape(null)).isNull();
}
@Test
@DisplayName("空字符串输入应返回空字符串")
void emptyInputShouldReturnEmpty() {
assertThat(HtmlEscapeUtil.unescape("")).isEmpty();
}
}
@Nested
@DisplayName("stripHtmlTags 方法测试")
class StripHtmlTagsTest {
@Test
@DisplayName("应移除HTML标签")
void shouldRemoveHtmlTags() {
String input = "<div>Hello <b>World</b></div>";
String result = HtmlEscapeUtil.stripHtmlTags(input);
assertThat(result).isEqualTo("Hello World");
}
@Test
@DisplayName("应移除自闭合标签")
void shouldRemoveSelfClosingTags() {
String result = HtmlEscapeUtil.stripHtmlTags("Text<br/>More<img src='x'/>");
assertThat(result).isEqualTo("TextMore");
}
@Test
@DisplayName("无标签文本应原样返回")
void plainTextShouldReturnUnchanged() {
String input = "Plain text without tags";
assertThat(HtmlEscapeUtil.stripHtmlTags(input)).isEqualTo(input);
}
@Test
@DisplayName("null输入应返回null")
void nullInputShouldReturnNull() {
assertThat(HtmlEscapeUtil.stripHtmlTags(null)).isNull();
}
@Test
@DisplayName("空字符串输入应返回空字符串")
void emptyInputShouldReturnEmpty() {
assertThat(HtmlEscapeUtil.stripHtmlTags("")).isEmpty();
}
}
@Nested
@DisplayName("sanitize 方法测试")
class SanitizeTest {
@Test
@DisplayName("应先移除HTML标签再转义特殊字符")
void shouldStripTagsThenEscape() {
String input = "<p>Hello & World</p>";
String result = HtmlEscapeUtil.sanitize(input);
assertThat(result).doesNotContain("<");
assertThat(result).doesNotContain(">");
assertThat(result).contains("&amp;");
}
@Test
@DisplayName("null输入应返回null")
void nullInputShouldReturnNull() {
assertThat(HtmlEscapeUtil.sanitize(null)).isNull();
}
@Test
@DisplayName("空字符串输入应返回空字符串")
void emptyInputShouldReturnEmpty() {
assertThat(HtmlEscapeUtil.sanitize("")).isEmpty();
}
}
@Nested
@DisplayName("containsHtmlTags 方法测试")
class ContainsHtmlTagsTest {
@Test
@DisplayName("包含HTML标签时返回true")
void shouldReturnTrueWhenContainsTags() {
assertThat(HtmlEscapeUtil.containsHtmlTags("<div>text</div>")).isTrue();
}
@Test
@DisplayName("不包含HTML标签时返回false")
void shouldReturnFalseWhenNoTags() {
assertThat(HtmlEscapeUtil.containsHtmlTags("plain text")).isFalse();
}
@Test
@DisplayName("null输入应返回false")
void nullInputShouldReturnFalse() {
assertThat(HtmlEscapeUtil.containsHtmlTags(null)).isFalse();
}
@Test
@DisplayName("空字符串输入应返回false")
void emptyInputShouldReturnFalse() {
assertThat(HtmlEscapeUtil.containsHtmlTags("")).isFalse();
}
}
}
@@ -0,0 +1,52 @@
package cn.novalon.gym.manage.common.util;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("SnowflakeId 单元测试")
class SnowflakeIdTest {
@Test
@DisplayName("nextId()应返回正数")
void nextIdShouldReturnPositiveLong() {
long id = SnowflakeId.nextId();
assertThat(id).isPositive();
}
@Test
@DisplayName("连续100次调用应生成不重复的ID")
void multipleCallsShouldGenerateUniqueIds() {
Set<Long> ids = new HashSet<>();
for (int i = 0; i < 100; i++) {
long id = SnowflakeId.nextId();
assertThat(ids.add(id))
.as("ID %d should be unique", id)
.isTrue();
}
assertThat(ids).hasSize(100);
}
@Test
@DisplayName("连续生成的ID应该是递增的")
void consecutiveIdsShouldBeIncreasing() {
long prev = SnowflakeId.nextId();
for (int i = 0; i < 10; i++) {
long curr = SnowflakeId.nextId();
assertThat(curr).isGreaterThan(prev);
prev = curr;
}
}
@Test
@DisplayName("getWorkerId()应返回有效的workerId")
void getWorkerIdShouldReturnValidId() {
long workerId = SnowflakeId.getWorkerId();
assertThat(workerId).isGreaterThanOrEqualTo(0);
}
}