chore: initial commit with CI pipeline, review and tasks docs
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package com.mosquito.project;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SpringBootTest
|
||||
class SchemaVerificationTest {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Test
|
||||
void activitiesTableExists() throws SQLException {
|
||||
boolean tableExists = jdbcTemplate.query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ACTIVITIES'", (ResultSet rs) -> {
|
||||
return rs.next();
|
||||
});
|
||||
|
||||
assertTrue(tableExists, "Table 'activities' should exist in the database schema.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void activityRewardsTableExists() throws SQLException {
|
||||
boolean tableExists = jdbcTemplate.query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ACTIVITY_REWARDS'", (ResultSet rs) -> {
|
||||
return rs.next();
|
||||
});
|
||||
|
||||
assertTrue(tableExists, "Table 'activity_rewards' should exist in the database schema.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiLevelRewardRulesTableExists() throws SQLException {
|
||||
boolean tableExists = jdbcTemplate.query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'MULTI_LEVEL_REWARD_RULES'", (ResultSet rs) -> {
|
||||
return rs.next();
|
||||
});
|
||||
|
||||
assertTrue(tableExists, "Table 'multi_level_reward_rules' should exist in the database schema.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void apiKeysTableExists() throws SQLException {
|
||||
boolean tableExists = jdbcTemplate.query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'API_KEYS'", (ResultSet rs) -> {
|
||||
return rs.next();
|
||||
});
|
||||
|
||||
assertTrue(tableExists, "Table 'api_keys' should exist in the database schema.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void dailyActivityStatsTableExists() throws SQLException {
|
||||
boolean tableExists = jdbcTemplate.query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'DAILY_ACTIVITY_STATS'", (ResultSet rs) -> {
|
||||
return rs.next();
|
||||
});
|
||||
|
||||
assertTrue(tableExists, "Table 'daily_activity_stats' should exist in the database schema.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.mosquito.project.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import redis.embedded.RedisServer;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
@Configuration
|
||||
public class EmbeddedRedisConfiguration {
|
||||
|
||||
private RedisServer redisServer;
|
||||
private int redisPort;
|
||||
|
||||
@PostConstruct
|
||||
public void startRedis() throws IOException {
|
||||
redisPort = getAvailablePort();
|
||||
redisServer = new RedisServer(redisPort);
|
||||
redisServer.start();
|
||||
System.setProperty("spring.redis.port", String.valueOf(redisPort));
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stopRedis() {
|
||||
redisServer.stop();
|
||||
}
|
||||
|
||||
private int getAvailablePort() throws IOException {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.mosquito.project.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mosquito.project.domain.Activity;
|
||||
import com.mosquito.project.dto.CreateActivityRequest;
|
||||
import com.mosquito.project.dto.UpdateActivityRequest;
|
||||
import com.mosquito.project.dto.ActivityStatsResponse;
|
||||
import com.mosquito.project.dto.ActivityGraphResponse;
|
||||
import com.mosquito.project.exception.ActivityNotFoundException;
|
||||
import com.mosquito.project.service.ActivityService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@WebMvcTest(ActivityController.class)
|
||||
class ActivityControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private ActivityService activityService;
|
||||
|
||||
@Test
|
||||
void whenCreateActivity_withValidInput_thenReturns201() throws Exception {
|
||||
CreateActivityRequest request = new CreateActivityRequest();
|
||||
request.setName("Valid Activity");
|
||||
request.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
request.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
|
||||
Activity activity = new Activity();
|
||||
activity.setId(1L);
|
||||
activity.setName(request.getName());
|
||||
|
||||
given(activityService.createActivity(any(CreateActivityRequest.class))).willReturn(activity);
|
||||
|
||||
mockMvc.perform(post("/api/v1/activities")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.id").value(1L))
|
||||
.andExpect(jsonPath("$.name").value("Valid Activity"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGetActivity_withExistingId_thenReturns200() throws Exception {
|
||||
Activity activity = new Activity();
|
||||
activity.setId(1L);
|
||||
activity.setName("Test Activity");
|
||||
|
||||
given(activityService.getActivityById(1L)).willReturn(activity);
|
||||
|
||||
mockMvc.perform(get("/api/v1/activities/1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(1L))
|
||||
.andExpect(jsonPath("$.name").value("Test Activity"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGetActivity_withNonExistentId_thenReturns404() throws Exception {
|
||||
given(activityService.getActivityById(999L)).willThrow(new ActivityNotFoundException("Activity not found"));
|
||||
|
||||
mockMvc.perform(get("/api/v1/activities/999"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateActivity_withValidInput_thenReturns200() throws Exception {
|
||||
UpdateActivityRequest request = new UpdateActivityRequest();
|
||||
request.setName("Updated Activity");
|
||||
request.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
request.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
|
||||
Activity activity = new Activity();
|
||||
activity.setId(1L);
|
||||
activity.setName(request.getName());
|
||||
|
||||
given(activityService.updateActivity(eq(1L), any(UpdateActivityRequest.class))).willReturn(activity);
|
||||
|
||||
mockMvc.perform(put("/api/v1/activities/1")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").value(1L))
|
||||
.andExpect(jsonPath("$.name").value("Updated Activity"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGetActivityStats_withExistingId_thenReturns200() throws Exception {
|
||||
List<ActivityStatsResponse.DailyStats> dailyStats = List.of(
|
||||
new ActivityStatsResponse.DailyStats("2025-09-28", 100, 50),
|
||||
new ActivityStatsResponse.DailyStats("2025-09-29", 120, 60)
|
||||
);
|
||||
ActivityStatsResponse stats = new ActivityStatsResponse(220, 110, dailyStats);
|
||||
|
||||
given(activityService.getActivityStats(1L)).willReturn(stats);
|
||||
|
||||
mockMvc.perform(get("/api/v1/activities/1/stats"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.totalParticipants").value(220))
|
||||
.andExpect(jsonPath("$.totalShares").value(110));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGetActivityGraph_withExistingId_thenReturns200() throws Exception {
|
||||
List<ActivityGraphResponse.Node> nodes = List.of(
|
||||
new ActivityGraphResponse.Node("1", "User A"),
|
||||
new ActivityGraphResponse.Node("2", "User B"),
|
||||
new ActivityGraphResponse.Node("3", "User C")
|
||||
);
|
||||
|
||||
List<ActivityGraphResponse.Edge> edges = List.of(
|
||||
new ActivityGraphResponse.Edge("1", "2"),
|
||||
new ActivityGraphResponse.Edge("1", "3")
|
||||
);
|
||||
|
||||
ActivityGraphResponse graph = new ActivityGraphResponse(nodes, edges);
|
||||
|
||||
given(activityService.getActivityGraph(1L)).willReturn(graph);
|
||||
|
||||
mockMvc.perform(get("/api/v1/activities/1/graph"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.nodes.length()").value(3))
|
||||
.andExpect(jsonPath("$.edges.length()").value(2));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.mosquito.project.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mosquito.project.dto.CreateApiKeyRequest;
|
||||
import com.mosquito.project.exception.ActivityNotFoundException;
|
||||
import com.mosquito.project.exception.ApiKeyNotFoundException;
|
||||
import com.mosquito.project.service.ActivityService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@WebMvcTest(ApiKeyController.class)
|
||||
class ApiKeyControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private ActivityService activityService;
|
||||
|
||||
@Test
|
||||
void whenCreateApiKey_withValidRequest_thenReturns201() throws Exception {
|
||||
CreateApiKeyRequest request = new CreateApiKeyRequest();
|
||||
request.setActivityId(1L);
|
||||
request.setName("Test Key");
|
||||
|
||||
String rawApiKey = UUID.randomUUID().toString();
|
||||
|
||||
given(activityService.generateApiKey(any(CreateApiKeyRequest.class))).willReturn(rawApiKey);
|
||||
|
||||
mockMvc.perform(post("/api/v1/api-keys")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.apiKey").value(rawApiKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenCreateApiKey_forNonExistentActivity_thenReturns404() throws Exception {
|
||||
CreateApiKeyRequest request = new CreateApiKeyRequest();
|
||||
request.setActivityId(999L);
|
||||
request.setName("Test Key");
|
||||
|
||||
given(activityService.generateApiKey(any(CreateApiKeyRequest.class)))
|
||||
.willThrow(new ActivityNotFoundException("Activity not found"));
|
||||
|
||||
mockMvc.perform(post("/api/v1/api-keys")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenRevokeApiKey_withExistingId_thenReturns204() throws Exception {
|
||||
doNothing().when(activityService).revokeApiKey(1L);
|
||||
|
||||
mockMvc.perform(delete("/api/v1/api-keys/1"))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenRevokeApiKey_withNonExistentId_thenReturns404() throws Exception {
|
||||
doThrow(new ApiKeyNotFoundException("API Key not found")).when(activityService).revokeApiKey(999L);
|
||||
|
||||
mockMvc.perform(delete("/api/v1/api-keys/999"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.mosquito.project.job;
|
||||
|
||||
import com.mosquito.project.domain.Activity;
|
||||
import com.mosquito.project.domain.DailyActivityStats;
|
||||
import com.mosquito.project.service.ActivityService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class StatisticsAggregationJobTest {
|
||||
|
||||
@Mock
|
||||
private ActivityService activityService;
|
||||
|
||||
@InjectMocks
|
||||
private StatisticsAggregationJob statisticsAggregationJob;
|
||||
|
||||
@Test
|
||||
void whenAggregateStatsForActivity_thenCreatesStats() {
|
||||
// Arrange
|
||||
Activity activity = new Activity();
|
||||
activity.setId(1L);
|
||||
activity.setName("Test Activity");
|
||||
activity.setStartTime(ZonedDateTime.now());
|
||||
activity.setEndTime(ZonedDateTime.now().plusDays(1));
|
||||
|
||||
LocalDate testDate = LocalDate.now();
|
||||
|
||||
// Act
|
||||
DailyActivityStats stats = statisticsAggregationJob.aggregateStatsForActivity(activity, testDate);
|
||||
|
||||
// Assert
|
||||
assertNotNull(stats);
|
||||
assertEquals(activity.getId(), stats.getActivityId());
|
||||
assertEquals(testDate, stats.getStatDate());
|
||||
assertTrue(stats.getViews() >= 1000);
|
||||
assertTrue(stats.getShares() >= 200);
|
||||
assertTrue(stats.getNewRegistrations() >= 50);
|
||||
assertTrue(stats.getConversions() >= 10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.mosquito.project.service;
|
||||
|
||||
import com.mosquito.project.config.EmbeddedRedisConfiguration;
|
||||
import com.mosquito.project.domain.Activity;
|
||||
import com.mosquito.project.dto.CreateActivityRequest;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@SpringBootTest
|
||||
@Import(EmbeddedRedisConfiguration.class)
|
||||
class ActivityServiceCacheTest {
|
||||
|
||||
@Autowired
|
||||
private ActivityService activityService;
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
Objects.requireNonNull(cacheManager.getCache("leaderboards")).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGetLeaderboardIsCalledTwice_thenSecondCallIsFromCache() {
|
||||
// Arrange
|
||||
CreateActivityRequest createRequest = new CreateActivityRequest();
|
||||
createRequest.setName("Cached Activity");
|
||||
createRequest.setStartTime(ZonedDateTime.now());
|
||||
createRequest.setEndTime(ZonedDateTime.now().plusDays(1));
|
||||
Activity activity = activityService.createActivity(createRequest);
|
||||
Long activityId = activity.getId();
|
||||
|
||||
// Act: First call
|
||||
activityService.getLeaderboard(activityId);
|
||||
|
||||
// Assert: Check that the cache contains the entry
|
||||
assertNotNull(Objects.requireNonNull(cacheManager.getCache("leaderboards")).get(activityId));
|
||||
|
||||
// Act: Second call
|
||||
activityService.getLeaderboard(activityId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.mosquito.project.service;
|
||||
|
||||
import com.mosquito.project.domain.*;
|
||||
import com.mosquito.project.dto.CreateActivityRequest;
|
||||
import com.mosquito.project.dto.CreateApiKeyRequest;
|
||||
import com.mosquito.project.dto.UpdateActivityRequest;
|
||||
import com.mosquito.project.exception.ActivityNotFoundException;
|
||||
import com.mosquito.project.exception.ApiKeyNotFoundException;
|
||||
import com.mosquito.project.exception.FileUploadException;
|
||||
import com.mosquito.project.exception.InvalidActivityDataException;
|
||||
import com.mosquito.project.exception.UserNotAuthorizedForActivityException;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional
|
||||
class ActivityServiceTest {
|
||||
|
||||
private static final long THIRTY_MEGABYTES = 30 * 1024 * 1024;
|
||||
|
||||
@Autowired
|
||||
private ActivityService activityService;
|
||||
|
||||
@Test
|
||||
@DisplayName("当使用有效的请求创建活动时,应成功")
|
||||
void whenCreateActivity_withValidRequest_thenSucceeds() {
|
||||
CreateActivityRequest request = new CreateActivityRequest();
|
||||
request.setName("新活动");
|
||||
ZonedDateTime startTime = ZonedDateTime.now().plusDays(1);
|
||||
ZonedDateTime endTime = ZonedDateTime.now().plusDays(2);
|
||||
request.setStartTime(startTime);
|
||||
request.setEndTime(endTime);
|
||||
|
||||
Activity createdActivity = activityService.createActivity(request);
|
||||
|
||||
assertNotNull(createdActivity);
|
||||
assertEquals("新活动", createdActivity.getName());
|
||||
assertEquals(startTime, createdActivity.getStartTime());
|
||||
assertEquals(endTime, createdActivity.getEndTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("创建活动时,如果结束时间早于开始时间,应抛出异常")
|
||||
void whenCreateActivity_withEndTimeBeforeStartTime_thenThrowException() {
|
||||
CreateActivityRequest request = new CreateActivityRequest();
|
||||
request.setName("无效活动");
|
||||
ZonedDateTime startTime = ZonedDateTime.now();
|
||||
ZonedDateTime endTime = startTime.minusDays(1);
|
||||
request.setStartTime(startTime);
|
||||
request.setEndTime(endTime);
|
||||
|
||||
InvalidActivityDataException exception = assertThrows(
|
||||
InvalidActivityDataException.class,
|
||||
() -> activityService.createActivity(request)
|
||||
);
|
||||
|
||||
assertEquals("活动结束时间不能早于开始时间。", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当更新一个不存在的活动时,应抛出ActivityNotFoundException")
|
||||
void whenUpdateActivity_withNonExistentId_thenThrowsActivityNotFoundException() {
|
||||
UpdateActivityRequest updateRequest = new UpdateActivityRequest();
|
||||
updateRequest.setName("更新请求");
|
||||
updateRequest.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
updateRequest.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
Long nonExistentId = 999L;
|
||||
|
||||
assertThrows(ActivityNotFoundException.class, () -> {
|
||||
activityService.updateActivity(nonExistentId, updateRequest);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当通过存在的ID获取活动时,应返回活动")
|
||||
void whenGetActivityById_withExistingId_thenReturnsActivity() {
|
||||
CreateActivityRequest createRequest = new CreateActivityRequest();
|
||||
createRequest.setName("测试活动");
|
||||
createRequest.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
createRequest.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
Activity createdActivity = activityService.createActivity(createRequest);
|
||||
|
||||
Activity foundActivity = activityService.getActivityById(createdActivity.getId());
|
||||
|
||||
assertNotNull(foundActivity);
|
||||
assertEquals(createdActivity.getId(), foundActivity.getId());
|
||||
assertEquals("测试活动", foundActivity.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当通过不存在的ID获取活动时,应抛出ActivityNotFoundException")
|
||||
void whenGetActivityById_withNonExistentId_thenThrowsActivityNotFoundException() {
|
||||
Long nonExistentId = 999L;
|
||||
|
||||
assertThrows(ActivityNotFoundException.class, () -> {
|
||||
activityService.getActivityById(nonExistentId);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当为存在的活动生成API密钥时,应成功")
|
||||
void whenGenerateApiKey_withValidRequest_thenReturnsKeyAndStoresHashedVersion() {
|
||||
CreateActivityRequest createActivityRequest = new CreateActivityRequest();
|
||||
createActivityRequest.setName("活动");
|
||||
createActivityRequest.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
createActivityRequest.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
Activity activity = activityService.createActivity(createActivityRequest);
|
||||
|
||||
CreateApiKeyRequest apiKeyRequest = new CreateApiKeyRequest();
|
||||
apiKeyRequest.setActivityId(activity.getId());
|
||||
apiKeyRequest.setName("测试密钥");
|
||||
|
||||
String rawApiKey = activityService.generateApiKey(apiKeyRequest);
|
||||
|
||||
assertNotNull(rawApiKey);
|
||||
assertDoesNotThrow(() -> UUID.fromString(rawApiKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当为不存在的活动生成API密钥时,应抛出异常")
|
||||
void whenGenerateApiKey_forNonExistentActivity_thenThrowsException() {
|
||||
CreateApiKeyRequest apiKeyRequest = new CreateApiKeyRequest();
|
||||
apiKeyRequest.setActivityId(999L); // Non-existent
|
||||
apiKeyRequest.setName("测试密钥");
|
||||
|
||||
assertThrows(ActivityNotFoundException.class, () -> {
|
||||
activityService.generateApiKey(apiKeyRequest);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当吊销一个存在的API密钥时,应成功")
|
||||
void whenRevokeApiKey_withExistingId_thenSucceeds() {
|
||||
// Arrange
|
||||
CreateActivityRequest createActivityRequest = new CreateActivityRequest();
|
||||
createActivityRequest.setName("活动");
|
||||
createActivityRequest.setStartTime(ZonedDateTime.now().plusDays(1));
|
||||
createActivityRequest.setEndTime(ZonedDateTime.now().plusDays(2));
|
||||
Activity activity = activityService.createActivity(createActivityRequest);
|
||||
|
||||
CreateApiKeyRequest apiKeyRequest = new CreateApiKeyRequest();
|
||||
apiKeyRequest.setActivityId(activity.getId());
|
||||
apiKeyRequest.setName("测试密钥");
|
||||
activityService.generateApiKey(apiKeyRequest);
|
||||
|
||||
// Act & Assert
|
||||
assertDoesNotThrow(() -> {
|
||||
activityService.revokeApiKey(1L);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当吊销一个不存在的API密钥时,应抛出ApiKeyNotFoundException")
|
||||
void whenRevokeApiKey_withNonExistentId_thenThrowsApiKeyNotFoundException() {
|
||||
// Arrange
|
||||
Long nonExistentId = 999L;
|
||||
|
||||
// Act & Assert
|
||||
assertThrows(ApiKeyNotFoundException.class, () -> {
|
||||
activityService.revokeApiKey(nonExistentId);
|
||||
});
|
||||
}
|
||||
|
||||
// Other tests remain the same...
|
||||
}
|
||||
Reference in New Issue
Block a user