test: 更新测试依赖并优化测试代码
Some checks failed
test/timeline-server/pipeline/head There was a failure building this commit

- 添加spring-boot-starter-test和mockito-junit-jupiter测试依赖
- 简化AlbumServicePropertyTest中的photoIdLists生成器
- 统一WebSocket测试中的any()参数类型为Object.class
- 优化TestDataGenerators中的代码格式和UserProfile时间类型
This commit is contained in:
2026-02-25 16:18:24 +08:00
parent 8080750078
commit edeb4fc168
5 changed files with 152 additions and 148 deletions

View File

@@ -133,6 +133,18 @@
<artifactId>jqwik</artifactId> <artifactId>jqwik</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -285,7 +285,6 @@ class AlbumServicePropertyTest {
@Provide @Provide
Arbitrary<List<String>> photoIdLists() { Arbitrary<List<String>> photoIdLists() {
return Arbitraries.integers().between(1, 10) return Arbitraries.integers().between(1, 10)
.flatMap(size -> Combinators.listOf(TestDataGenerators.photoIds()) .flatMap(size -> TestDataGenerators.photoIds().list().ofSize(size));
.ofSize(size));
} }
} }

View File

@@ -186,7 +186,7 @@ class CommentWebSocketTest {
// Simulate WebSocket failure // Simulate WebSocket failure
doThrow(new RuntimeException("WebSocket error")) doThrow(new RuntimeException("WebSocket error"))
.when(messagingTemplate).convertAndSend(anyString(), any()); .when(messagingTemplate).convertAndSend(anyString(), any(Object.class));
// Act - should not throw exception // Act - should not throw exception
CommentDto result = commentService.createComment("user123", request); CommentDto result = commentService.createComment("user123", request);
@@ -196,6 +196,6 @@ class CommentWebSocketTest {
assertEquals("Test comment", result.getContent()); assertEquals("Test comment", result.getContent());
// Verify the WebSocket send was attempted // Verify the WebSocket send was attempted
verify(messagingTemplate, times(1)).convertAndSend(anyString(), any()); verify(messagingTemplate, times(1)).convertAndSend(anyString(), any(Object.class));
} }
} }

View File

@@ -76,12 +76,12 @@ public class ReactionWebSocketTest {
// Assert // Assert
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class); ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class);
verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture()); verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture());
// 验证主题格式 // 验证主题格式
assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue()); assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue());
// 验证事件内容 // 验证事件内容
ReactionEventDto event = eventCaptor.getValue(); ReactionEventDto event = eventCaptor.getValue();
assertEquals(ReactionEventDto.ReactionEventType.CREATED, event.getEventType()); assertEquals(ReactionEventDto.ReactionEventType.CREATED, event.getEventType());
@@ -123,12 +123,12 @@ public class ReactionWebSocketTest {
// Assert // Assert
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class); ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class);
verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture()); verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture());
// 验证主题格式 // 验证主题格式
assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue()); assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue());
// 验证事件内容 // 验证事件内容
ReactionEventDto event = eventCaptor.getValue(); ReactionEventDto event = eventCaptor.getValue();
assertEquals(ReactionEventDto.ReactionEventType.UPDATED, event.getEventType()); assertEquals(ReactionEventDto.ReactionEventType.UPDATED, event.getEventType());
@@ -147,12 +147,12 @@ public class ReactionWebSocketTest {
// Assert // Assert
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class); ArgumentCaptor<ReactionEventDto> eventCaptor = ArgumentCaptor.forClass(ReactionEventDto.class);
verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture()); verify(messagingTemplate).convertAndSend(topicCaptor.capture(), eventCaptor.capture());
// 验证主题格式 // 验证主题格式
assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue()); assertEquals("/topic/reactions/STORY_ITEM/story123", topicCaptor.getValue());
// 验证事件内容 // 验证事件内容
ReactionEventDto event = eventCaptor.getValue(); ReactionEventDto event = eventCaptor.getValue();
assertEquals(ReactionEventDto.ReactionEventType.DELETED, event.getEventType()); assertEquals(ReactionEventDto.ReactionEventType.DELETED, event.getEventType());
@@ -169,10 +169,10 @@ public class ReactionWebSocketTest {
when(reactionMapper.insert(any(Reaction.class))).thenReturn(1); when(reactionMapper.insert(any(Reaction.class))).thenReturn(1);
when(reactionMapper.findByEntityAndUser("STORY_ITEM", "story123", "user123")).thenReturn(testReaction); when(reactionMapper.findByEntityAndUser("STORY_ITEM", "story123", "user123")).thenReturn(testReaction);
when(userMapper.selectByUserId("user123")).thenReturn(testUser); when(userMapper.selectByUserId("user123")).thenReturn(testUser);
// 模拟WebSocket发送失败 // 模拟WebSocket发送失败
doThrow(new RuntimeException("WebSocket connection failed")) doThrow(new RuntimeException("WebSocket connection failed"))
.when(messagingTemplate).convertAndSend(anyString(), any()); .when(messagingTemplate).convertAndSend(anyString(), any(Object.class));
// Act & Assert - 不应该抛出异常 // Act & Assert - 不应该抛出异常
assertDoesNotThrow(() -> { assertDoesNotThrow(() -> {
@@ -188,14 +188,14 @@ public class ReactionWebSocketTest {
// Test STORY_ITEM // Test STORY_ITEM
when(reactionMapper.findByEntityAndUser(anyString(), anyString(), anyString())).thenReturn(null); when(reactionMapper.findByEntityAndUser(anyString(), anyString(), anyString())).thenReturn(null);
when(reactionMapper.insert(any(Reaction.class))).thenReturn(1); when(reactionMapper.insert(any(Reaction.class))).thenReturn(1);
Reaction storyReaction = new Reaction(); Reaction storyReaction = new Reaction();
storyReaction.setEntityType("STORY_ITEM"); storyReaction.setEntityType("STORY_ITEM");
storyReaction.setEntityId("story456"); storyReaction.setEntityId("story456");
storyReaction.setUserId("user123"); storyReaction.setUserId("user123");
storyReaction.setReactionType("LIKE"); storyReaction.setReactionType("LIKE");
storyReaction.setCreateTime(LocalDateTime.now()); storyReaction.setCreateTime(LocalDateTime.now());
when(reactionMapper.findByEntityAndUser("STORY_ITEM", "story456", "user123")).thenReturn(storyReaction); when(reactionMapper.findByEntityAndUser("STORY_ITEM", "story456", "user123")).thenReturn(storyReaction);
when(userMapper.selectByUserId("user123")).thenReturn(testUser); when(userMapper.selectByUserId("user123")).thenReturn(testUser);
@@ -207,14 +207,14 @@ public class ReactionWebSocketTest {
// Test PHOTO // Test PHOTO
reset(messagingTemplate); reset(messagingTemplate);
Reaction photoReaction = new Reaction(); Reaction photoReaction = new Reaction();
photoReaction.setEntityType("PHOTO"); photoReaction.setEntityType("PHOTO");
photoReaction.setEntityId("photo789"); photoReaction.setEntityId("photo789");
photoReaction.setUserId("user123"); photoReaction.setUserId("user123");
photoReaction.setReactionType("LOVE"); photoReaction.setReactionType("LOVE");
photoReaction.setCreateTime(LocalDateTime.now()); photoReaction.setCreateTime(LocalDateTime.now());
when(reactionMapper.findByEntityAndUser("PHOTO", "photo789", "user123")).thenReturn(photoReaction); when(reactionMapper.findByEntityAndUser("PHOTO", "photo789", "user123")).thenReturn(photoReaction);
reactionService.addOrUpdateReaction("user123", "PHOTO", "photo789", "LOVE"); reactionService.addOrUpdateReaction("user123", "PHOTO", "photo789", "LOVE");
@@ -238,7 +238,7 @@ public class ReactionWebSocketTest {
reactionService.addOrUpdateReaction("user123", "STORY_ITEM", "story123", "LIKE"); reactionService.addOrUpdateReaction("user123", "STORY_ITEM", "story123", "LIKE");
// Assert - 不应该发送WebSocket消息 // Assert - 不应该发送WebSocket消息
verify(messagingTemplate, never()).convertAndSend(anyString(), any()); verify(messagingTemplate, never()).convertAndSend(anyString(), any(Object.class));
} }
@Test @Test
@@ -250,6 +250,6 @@ public class ReactionWebSocketTest {
reactionService.removeReaction("user123", "STORY_ITEM", "story123"); reactionService.removeReaction("user123", "STORY_ITEM", "story123");
// Assert - 不应该发送WebSocket消息 // Assert - 不应该发送WebSocket消息
verify(messagingTemplate, never()).convertAndSend(anyString(), any()); verify(messagingTemplate, never()).convertAndSend(anyString(), any(Object.class));
} }
} }

View File

@@ -7,6 +7,7 @@ import net.jqwik.api.Arbitrary;
import net.jqwik.api.Combinators; import net.jqwik.api.Combinators;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID; import java.util.UUID;
/** /**
@@ -20,25 +21,24 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<Album> albums() { public static Arbitrary<Album> albums() {
return Combinators.combine( return Combinators.combine(
instanceIds(), instanceIds(),
userIds(), userIds(),
albumNames(), albumNames(),
descriptions(), descriptions(),
photoIds(), photoIds(),
photoCounts() photoCounts()).as((instanceId, userId, name, description, coverPhotoId, photoCount) -> {
).as((instanceId, userId, name, description, coverPhotoId, photoCount) -> { Album album = new Album();
Album album = new Album(); album.setInstanceId(instanceId);
album.setInstanceId(instanceId); album.setUserId(userId);
album.setUserId(userId); album.setName(name);
album.setName(name); album.setDescription(description);
album.setDescription(description); album.setCoverPhotoId(coverPhotoId);
album.setCoverPhotoId(coverPhotoId); album.setPhotoCount(photoCount);
album.setPhotoCount(photoCount); album.setCreateTime(LocalDateTime.now());
album.setCreateTime(LocalDateTime.now()); album.setUpdateTime(LocalDateTime.now());
album.setUpdateTime(LocalDateTime.now()); album.setIsDelete(0);
album.setIsDelete(0); return album;
return album; });
});
} }
/** /**
@@ -46,23 +46,22 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<Comment> comments() { public static Arbitrary<Comment> comments() {
return Combinators.combine( return Combinators.combine(
instanceIds(), instanceIds(),
entityTypes(), entityTypes(),
entityIds(), entityIds(),
userIds(), userIds(),
commentContents() commentContents()).as((instanceId, entityType, entityId, userId, content) -> {
).as((instanceId, entityType, entityId, userId, content) -> { Comment comment = new Comment();
Comment comment = new Comment(); comment.setInstanceId(instanceId);
comment.setInstanceId(instanceId); comment.setEntityType(entityType);
comment.setEntityType(entityType); comment.setEntityId(entityId);
comment.setEntityId(entityId); comment.setUserId(userId);
comment.setUserId(userId); comment.setContent(content);
comment.setContent(content); comment.setCreateTime(LocalDateTime.now());
comment.setCreateTime(LocalDateTime.now()); comment.setUpdateTime(LocalDateTime.now());
comment.setUpdateTime(LocalDateTime.now()); comment.setIsDelete(0);
comment.setIsDelete(0); return comment;
return comment; });
});
} }
/** /**
@@ -70,20 +69,19 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<Reaction> reactions() { public static Arbitrary<Reaction> reactions() {
return Combinators.combine( return Combinators.combine(
entityTypes(), entityTypes(),
entityIds(), entityIds(),
userIds(), userIds(),
reactionTypes() reactionTypes()).as((entityType, entityId, userId, reactionType) -> {
).as((entityType, entityId, userId, reactionType) -> { Reaction reaction = new Reaction();
Reaction reaction = new Reaction(); reaction.setEntityType(entityType);
reaction.setEntityType(entityType); reaction.setEntityId(entityId);
reaction.setEntityId(entityId); reaction.setUserId(userId);
reaction.setUserId(userId); reaction.setReactionType(reactionType);
reaction.setReactionType(reactionType); reaction.setCreateTime(LocalDateTime.now());
reaction.setCreateTime(LocalDateTime.now()); reaction.setUpdateTime(LocalDateTime.now());
reaction.setUpdateTime(LocalDateTime.now()); return reaction;
return reaction; });
});
} }
/** /**
@@ -91,25 +89,24 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<UserPreferences> userPreferences() { public static Arbitrary<UserPreferences> userPreferences() {
return Combinators.combine( return Combinators.combine(
userIds(), userIds(),
themeModes(), themeModes(),
layoutTypes(), layoutTypes(),
cardSizes(), cardSizes(),
displayModes() displayModes()).as((userId, themeMode, layout, cardSize, displayMode) -> {
).as((userId, themeMode, layout, cardSize, displayMode) -> { UserPreferences prefs = new UserPreferences();
UserPreferences prefs = new UserPreferences(); prefs.setUserId(userId);
prefs.setUserId(userId); prefs.setThemeMode(themeMode);
prefs.setThemeMode(themeMode); prefs.setColorScheme("default");
prefs.setColorScheme("default"); prefs.setGalleryLayout(layout);
prefs.setGalleryLayout(layout); prefs.setTimelineLayout(layout);
prefs.setTimelineLayout(layout); prefs.setAlbumLayout(layout);
prefs.setAlbumLayout(layout); prefs.setCardSize(cardSize);
prefs.setCardSize(cardSize); prefs.setTimelineDisplayMode(displayMode);
prefs.setTimelineDisplayMode(displayMode); prefs.setCreateTime(LocalDateTime.now());
prefs.setCreateTime(LocalDateTime.now()); prefs.setUpdateTime(LocalDateTime.now());
prefs.setUpdateTime(LocalDateTime.now()); return prefs;
return prefs; });
});
} }
/** /**
@@ -117,18 +114,17 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<UserProfile> userProfiles() { public static Arbitrary<UserProfile> userProfiles() {
return Combinators.combine( return Combinators.combine(
userIds(), userIds(),
urls(), urls(),
bios() bios()).as((userId, coverPhotoUrl, bio) -> {
).as((userId, coverPhotoUrl, bio) -> { UserProfile profile = new UserProfile();
UserProfile profile = new UserProfile(); profile.setUserId(userId);
profile.setUserId(userId); profile.setCoverPhotoUrl(coverPhotoUrl);
profile.setCoverPhotoUrl(coverPhotoUrl); profile.setBio(bio);
profile.setBio(bio); profile.setCreateTime(new Date());
profile.setCreateTime(LocalDateTime.now()); profile.setUpdateTime(new Date());
profile.setUpdateTime(LocalDateTime.now()); return profile;
return profile; });
});
} }
/** /**
@@ -136,14 +132,13 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<CreateAlbumRequest> createAlbumRequests() { public static Arbitrary<CreateAlbumRequest> createAlbumRequests() {
return Combinators.combine( return Combinators.combine(
albumNames(), albumNames(),
descriptions() descriptions()).as((name, description) -> {
).as((name, description) -> { CreateAlbumRequest request = new CreateAlbumRequest();
CreateAlbumRequest request = new CreateAlbumRequest(); request.setName(name);
request.setName(name); request.setDescription(description);
request.setDescription(description); return request;
return request; });
});
} }
/** /**
@@ -151,16 +146,15 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<CreateCommentRequest> createCommentRequests() { public static Arbitrary<CreateCommentRequest> createCommentRequests() {
return Combinators.combine( return Combinators.combine(
entityTypes(), entityTypes(),
entityIds(), entityIds(),
commentContents() commentContents()).as((entityType, entityId, content) -> {
).as((entityType, entityId, content) -> { CreateCommentRequest request = new CreateCommentRequest();
CreateCommentRequest request = new CreateCommentRequest(); request.setEntityType(entityType);
request.setEntityType(entityType); request.setEntityId(entityId);
request.setEntityId(entityId); request.setContent(content);
request.setContent(content); return request;
return request; });
});
} }
// ========== 基础数据生成器 ========== // ========== 基础数据生成器 ==========
@@ -183,46 +177,46 @@ public class TestDataGenerators {
public static Arbitrary<String> albumNames() { public static Arbitrary<String> albumNames() {
return Arbitraries.strings() return Arbitraries.strings()
.alpha() .alpha()
.ofMinLength(1) .ofMinLength(1)
.ofMaxLength(50) .ofMaxLength(50)
.map(s -> "Album " + s); .map(s -> "Album " + s);
} }
public static Arbitrary<String> descriptions() { public static Arbitrary<String> descriptions() {
return Arbitraries.strings() return Arbitraries.strings()
.alpha() .alpha()
.numeric() .numeric()
.withChars(' ', '.', ',') .withChars(' ', '.', ',')
.ofMinLength(0) .ofMinLength(0)
.ofMaxLength(200); .ofMaxLength(200);
} }
public static Arbitrary<String> commentContents() { public static Arbitrary<String> commentContents() {
return Arbitraries.strings() return Arbitraries.strings()
.alpha() .alpha()
.numeric() .numeric()
.withChars(' ', '.', ',', '!', '?') .withChars(' ', '.', ',', '!', '?')
.ofMinLength(1) .ofMinLength(1)
.ofMaxLength(1000); .ofMaxLength(1000);
} }
public static Arbitrary<String> bios() { public static Arbitrary<String> bios() {
return Arbitraries.strings() return Arbitraries.strings()
.alpha() .alpha()
.numeric() .numeric()
.withChars(' ', '.', ',') .withChars(' ', '.', ',')
.ofMinLength(0) .ofMinLength(0)
.ofMaxLength(500); .ofMaxLength(500);
} }
public static Arbitrary<String> urls() { public static Arbitrary<String> urls() {
return Arbitraries.strings() return Arbitraries.strings()
.alpha() .alpha()
.numeric() .numeric()
.ofMinLength(10) .ofMinLength(10)
.ofMaxLength(50) .ofMaxLength(50)
.map(s -> "https://example.com/" + s + ".jpg"); .map(s -> "https://example.com/" + s + ".jpg");
} }
public static Arbitrary<Integer> photoCounts() { public static Arbitrary<Integer> photoCounts() {
@@ -265,9 +259,8 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<String> monthPeriods() { public static Arbitrary<String> monthPeriods() {
return Combinators.combine( return Combinators.combine(
Arbitraries.integers().between(2020, 2024), Arbitraries.integers().between(2020, 2024),
Arbitraries.integers().between(1, 12) Arbitraries.integers().between(1, 12)).as((year, month) -> String.format("%d-%02d", year, month));
).as((year, month) -> String.format("%d-%02d", year, month));
} }
/** /**
@@ -275,7 +268,7 @@ public class TestDataGenerators {
*/ */
public static Arbitrary<String> yearPeriods() { public static Arbitrary<String> yearPeriods() {
return Arbitraries.integers().between(2020, 2024) return Arbitraries.integers().between(2020, 2024)
.map(String::valueOf); .map(String::valueOf);
} }
/** /**