first runnable version
This commit is contained in:
@@ -4,6 +4,7 @@ import com.yoyuzh.auth.dto.AuthResponse;
|
||||
import com.yoyuzh.auth.dto.LoginRequest;
|
||||
import com.yoyuzh.auth.dto.RegisterRequest;
|
||||
import com.yoyuzh.common.BusinessException;
|
||||
import com.yoyuzh.files.FileService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -38,6 +39,9 @@ class AuthServiceTest {
|
||||
@Mock
|
||||
private JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Mock
|
||||
private FileService fileService;
|
||||
|
||||
@InjectMocks
|
||||
private AuthService authService;
|
||||
|
||||
@@ -60,6 +64,7 @@ class AuthServiceTest {
|
||||
assertThat(response.token()).isEqualTo("jwt-token");
|
||||
assertThat(response.user().username()).isEqualTo("alice");
|
||||
verify(passwordEncoder).encode("plain-password");
|
||||
verify(fileService).ensureDefaultDirectories(any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,6 +95,7 @@ class AuthServiceTest {
|
||||
new UsernamePasswordAuthenticationToken("alice", "plain-password"));
|
||||
assertThat(response.token()).isEqualTo("jwt-token");
|
||||
assertThat(response.user().email()).isEqualTo("alice@example.com");
|
||||
verify(fileService).ensureDefaultDirectories(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -102,4 +108,22 @@ class AuthServiceTest {
|
||||
.isInstanceOf(BusinessException.class)
|
||||
.hasMessageContaining("用户名或密码错误");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateDefaultDirectoriesForDevLoginUser() {
|
||||
when(userRepository.findByUsername("demo")).thenReturn(Optional.empty());
|
||||
when(passwordEncoder.encode("1")).thenReturn("encoded-password");
|
||||
when(userRepository.save(any(User.class))).thenAnswer(invocation -> {
|
||||
User user = invocation.getArgument(0);
|
||||
user.setId(9L);
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
return user;
|
||||
});
|
||||
when(jwtTokenProvider.generateToken(9L, "demo")).thenReturn("jwt-token");
|
||||
|
||||
AuthResponse response = authService.devLogin("demo");
|
||||
|
||||
assertThat(response.user().username()).isEqualTo("demo");
|
||||
verify(fileService).ensureDefaultDirectories(any(User.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.yoyuzh.auth;
|
||||
|
||||
import com.yoyuzh.config.FileStorageProperties;
|
||||
import com.yoyuzh.files.FileService;
|
||||
import com.yoyuzh.files.StoredFileRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DevBootstrapDataInitializerTest {
|
||||
|
||||
@Mock
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Mock
|
||||
private FileService fileService;
|
||||
|
||||
@Mock
|
||||
private StoredFileRepository storedFileRepository;
|
||||
|
||||
@Mock
|
||||
private FileStorageProperties fileStorageProperties;
|
||||
|
||||
@InjectMocks
|
||||
private DevBootstrapDataInitializer initializer;
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void shouldCreateInitialDevUsersWhenMissing() throws Exception {
|
||||
when(userRepository.findByUsername("portal-demo")).thenReturn(Optional.empty());
|
||||
when(userRepository.findByUsername("portal-study")).thenReturn(Optional.empty());
|
||||
when(userRepository.findByUsername("portal-design")).thenReturn(Optional.empty());
|
||||
when(passwordEncoder.encode("portal123456")).thenReturn("encoded-demo-password");
|
||||
when(passwordEncoder.encode("study123456")).thenReturn("encoded-study-password");
|
||||
when(passwordEncoder.encode("design123456")).thenReturn("encoded-design-password");
|
||||
when(storedFileRepository.existsByUserIdAndPathAndFilename(anyLong(), anyString(), anyString())).thenReturn(false);
|
||||
when(fileStorageProperties.getRootDir()).thenReturn(tempDir.toString());
|
||||
List<User> savedUsers = new ArrayList<>();
|
||||
when(userRepository.save(any(User.class))).thenAnswer(invocation -> {
|
||||
User user = invocation.getArgument(0);
|
||||
user.setId((long) (savedUsers.size() + 1));
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
savedUsers.add(user);
|
||||
return user;
|
||||
});
|
||||
|
||||
initializer.run();
|
||||
|
||||
verify(userRepository, times(3)).save(any(User.class));
|
||||
verify(fileService, times(3)).ensureDefaultDirectories(any(User.class));
|
||||
org.assertj.core.api.Assertions.assertThat(savedUsers)
|
||||
.extracting(User::getUsername)
|
||||
.containsExactly("portal-demo", "portal-study", "portal-design");
|
||||
verify(storedFileRepository, times(9)).save(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.yoyuzh.cqu;
|
||||
|
||||
import com.yoyuzh.PortalBackendApplication;
|
||||
import com.yoyuzh.auth.User;
|
||||
import com.yoyuzh.auth.UserRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SpringBootTest(
|
||||
classes = PortalBackendApplication.class,
|
||||
properties = {
|
||||
"spring.datasource.url=jdbc:h2:mem:cqu_tx_test;MODE=MySQL;DB_CLOSE_DELAY=-1",
|
||||
"spring.datasource.driver-class-name=org.h2.Driver",
|
||||
"spring.datasource.username=sa",
|
||||
"spring.datasource.password=",
|
||||
"spring.jpa.hibernate.ddl-auto=create-drop",
|
||||
"app.cqu.require-login=true",
|
||||
"app.cqu.mock-enabled=false"
|
||||
}
|
||||
)
|
||||
class CquDataServiceTransactionTest {
|
||||
|
||||
@Autowired
|
||||
private CquDataService cquDataService;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private GradeRepository gradeRepository;
|
||||
|
||||
@MockBean
|
||||
private CquApiClient cquApiClient;
|
||||
|
||||
@Test
|
||||
void shouldPersistGradesInsideTransactionForLoggedInUser() {
|
||||
User user = new User();
|
||||
user.setUsername("portal-demo");
|
||||
user.setEmail("portal-demo@example.com");
|
||||
user.setPasswordHash("encoded");
|
||||
user = userRepository.save(user);
|
||||
|
||||
Grade existing = new Grade();
|
||||
existing.setUser(user);
|
||||
existing.setCourseName("Old Java");
|
||||
existing.setGrade(60D);
|
||||
existing.setSemester("2025-spring");
|
||||
existing.setStudentId("2023123456");
|
||||
gradeRepository.save(existing);
|
||||
|
||||
when(cquApiClient.fetchGrades("2025-spring", "2023123456")).thenReturn(List.of(
|
||||
Map.of(
|
||||
"courseName", "Java",
|
||||
"grade", 95,
|
||||
"semester", "2025-spring"
|
||||
)
|
||||
));
|
||||
|
||||
List<GradeResponse> response = cquDataService.getGrades(user, "2025-spring", "2023123456");
|
||||
|
||||
assertThat(response).hasSize(1);
|
||||
assertThat(response.get(0).courseName()).isEqualTo("Java");
|
||||
assertThat(response.get(0).grade()).isEqualTo(95D);
|
||||
assertThat(gradeRepository.findByUserIdAndStudentIdOrderBySemesterAscGradeDesc(user.getId(), "2023123456"))
|
||||
.hasSize(1)
|
||||
.first()
|
||||
.extracting(Grade::getCourseName)
|
||||
.isEqualTo("Java");
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,17 @@ class CquMockDataFactoryTest {
|
||||
assertThat(result.get(0)).containsEntry("studentId", "20230001");
|
||||
assertThat(result.get(0)).containsKey("grade");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnDifferentMockDataForDifferentStudents() {
|
||||
List<Map<String, Object>> firstSchedule = CquMockDataFactory.createSchedule("2025-2026-1", "2023123456");
|
||||
List<Map<String, Object>> secondSchedule = CquMockDataFactory.createSchedule("2025-2026-1", "2022456789");
|
||||
List<Map<String, Object>> firstGrades = CquMockDataFactory.createGrades("2025-2026-1", "2023123456");
|
||||
List<Map<String, Object>> secondGrades = CquMockDataFactory.createGrades("2025-2026-1", "2022456789");
|
||||
|
||||
assertThat(firstSchedule).extracting(item -> item.get("courseName"))
|
||||
.isNotEqualTo(secondSchedule.stream().map(item -> item.get("courseName")).toList());
|
||||
assertThat(firstGrades).extracting(item -> item.get("grade"))
|
||||
.isNotEqualTo(secondGrades.stream().map(item -> item.get("grade")).toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@@ -22,6 +21,8 @@ import java.util.Optional;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -89,6 +90,25 @@ class FileServiceTest {
|
||||
assertThat(result.items().get(0).filename()).isEqualTo("notes.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateDefaultDirectoriesForUserWorkspace() {
|
||||
User user = createUser(7L);
|
||||
when(storedFileRepository.existsByUserIdAndPathAndFilename(7L, "/", "下载")).thenReturn(false);
|
||||
when(storedFileRepository.existsByUserIdAndPathAndFilename(7L, "/", "文档")).thenReturn(false);
|
||||
when(storedFileRepository.existsByUserIdAndPathAndFilename(7L, "/", "图片")).thenReturn(false);
|
||||
when(storedFileRepository.save(any(StoredFile.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
fileService.ensureDefaultDirectories(user);
|
||||
|
||||
assertThat(tempDir.resolve("7/下载")).exists();
|
||||
assertThat(tempDir.resolve("7/文档")).exists();
|
||||
assertThat(tempDir.resolve("7/图片")).exists();
|
||||
verify(storedFileRepository).existsByUserIdAndPathAndFilename(7L, "/", "下载");
|
||||
verify(storedFileRepository).existsByUserIdAndPathAndFilename(7L, "/", "文档");
|
||||
verify(storedFileRepository).existsByUserIdAndPathAndFilename(7L, "/", "图片");
|
||||
verify(storedFileRepository, times(3)).save(any(StoredFile.class));
|
||||
}
|
||||
|
||||
private User createUser(Long id) {
|
||||
User user = new User();
|
||||
user.setId(id);
|
||||
|
||||
Reference in New Issue
Block a user