Compare commits
13 Commits
cd98de9213
...
master
Author | SHA1 | Date | |
---|---|---|---|
a663a73ff1 | |||
2d27ebea35 | |||
d8b7943646 | |||
f58c1813ff | |||
57253951d3 | |||
6aec72e6ab | |||
6c1f6d824e | |||
c668251a3e | |||
da38955955 | |||
3afb26202b | |||
c58105b8ca | |||
ef5f9f2853 | |||
dcc6821d10 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target/
|
@ -1,2 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
|
@ -1,4 +1,4 @@
|
||||
activeProfiles=pom.xml
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
|
@ -2,9 +2,13 @@ package co.jp.app.common;
|
||||
|
||||
|
||||
public class ApiResponse<T> {
|
||||
//成功状况判定
|
||||
private boolean success;
|
||||
//状态码
|
||||
private int code;
|
||||
//状态信息
|
||||
private String message;
|
||||
//数据
|
||||
private T data;
|
||||
|
||||
private ApiResponse(ResultCode resultCode, T data) {
|
||||
@ -14,12 +18,13 @@ public class ApiResponse<T> {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(ResultCode.SUCCESS, data);
|
||||
private ApiResponse() {
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success() {
|
||||
return success(null);
|
||||
public static <T> ApiResponse<T> fail() {return success(null);}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(ResultCode.SUCCESS, data);
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> fail(ResultCode resultCode) {
|
||||
|
@ -28,7 +28,11 @@ public enum ResultCode {
|
||||
// 注册相关
|
||||
// USER_REGISTRATION_SUCCESS(3000, "用户注册成功"),
|
||||
USER_EMAIL_ALREADY_EXISTS(3001, "Email already exists"),
|
||||
// USER_USERNAME_ALREADY_EXISTS(3002, "Username"),
|
||||
|
||||
USER_USERNAME_ALREADY_EXISTS(3002, "Username"),
|
||||
|
||||
USER_EMAIL_NOT_VALID(3006, "Email is not valid"),
|
||||
|
||||
USER_PASSWORD_TOO_SHORT(3003, "password too short"),
|
||||
USER_PASSWORD_TOO_WEAK(3004, "password too weak"),
|
||||
USER_REGISTRATION_FAILED(3005, "User registration failed"),
|
||||
|
@ -1,9 +1,6 @@
|
||||
package co.jp.app.config.security;
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
import co.jp.app.config.security.filter.JwtAuthenticationFilter;
|
||||
>>>>>>> 2aae88278c46cf937380317aae1f9d229bcb3c37
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@ -13,12 +10,12 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
import co.jp.app.config.security.filter.JwtAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
@ -49,12 +46,13 @@ public class SecurityConfig {
|
||||
return authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
// http config
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.csrf(AbstractHttpConfigurer::disable)
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/user/login", "/api/user/register", "/api/inuhouse").permitAll()
|
||||
.requestMatchers("/api/user/login", "/api/user/register", "/api/inuhouse", "/api/dogs/pet").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.authenticationProvider(authenticationProvider())
|
||||
|
@ -1,7 +1,12 @@
|
||||
package co.jp.app.config.security.filter;
|
||||
|
||||
import co.jp.app.service.JwtService;
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@ -11,16 +16,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
<<<<<<< HEAD
|
||||
import co.jp.app.service.JwtService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
=======
|
||||
>>>>>>> 2aae88278c46cf937380317aae1f9d229bcb3c37
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@ -40,14 +35,17 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
final String jwt;
|
||||
final String username;
|
||||
|
||||
//不需要token,直接返回Chain
|
||||
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
//透过token读取username
|
||||
jwt = authHeader.substring(7);
|
||||
username = jwtService.extractUsername(jwt);
|
||||
|
||||
//如果username为空且认证为空
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||
if (jwtService.isTokenValid(jwt, userDetails)) {
|
||||
@ -58,7 +56,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||
}
|
||||
}
|
||||
|
||||
//name非数字特殊符号,英文半角,密码规则大小写特殊,email符合格式
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ public class DownloadController {
|
||||
@Autowired
|
||||
private PetService service;
|
||||
|
||||
@GetMapping("/api/dogs/download")
|
||||
@GetMapping("/download-image")
|
||||
public ResponseEntity<?> downloadById(@RequestParam List<Integer> id) {
|
||||
List<PetEntity> list = service.getPetByID(id);
|
||||
return ResponseEntity.ok(list);
|
||||
|
@ -18,7 +18,7 @@ public class PetController {
|
||||
@Autowired
|
||||
private PetService service;
|
||||
|
||||
@GetMapping("/api/dogs/pet")
|
||||
@GetMapping("/inuhouse")
|
||||
public ResponseEntity<?> getListByEntities(@RequestParam List<Integer> id) {
|
||||
|
||||
List<PetEntity> list = service.getPetByID(id);
|
||||
|
@ -19,7 +19,7 @@ public class UploadController {
|
||||
@Autowired
|
||||
private UploadService service;
|
||||
|
||||
@PostMapping("/api/dogs/upload")
|
||||
@PostMapping("/upload")
|
||||
public ResponseEntity<?> upload() {
|
||||
List<PetEntity> list = new ArrayList<PetEntity>();
|
||||
|
||||
|
@ -1,30 +1,29 @@
|
||||
package co.jp.app.controller;
|
||||
|
||||
import co.jp.app.common.ApiResponse;
|
||||
import co.jp.app.common.ResultCode;
|
||||
import co.jp.app.dto.LoginDto;
|
||||
import co.jp.app.dto.RegistrationDto;
|
||||
import co.jp.app.dto.UserDto;
|
||||
import co.jp.app.service.JwtService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import co.jp.app.entity.UserEntity;
|
||||
import co.jp.app.service.UserService;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import co.jp.app.common.ApiResponse;
|
||||
import co.jp.app.dto.LoginDto;
|
||||
import co.jp.app.dto.RegistrationDto;
|
||||
import co.jp.app.dto.UserDto;
|
||||
import co.jp.app.entity.UserEntity;
|
||||
import co.jp.app.service.JwtService;
|
||||
import co.jp.app.service.UserService;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
@ -37,7 +36,7 @@ public class UserController {
|
||||
this.jwtService = jwtService;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
@PostMapping("/api/user/register")
|
||||
public ResponseEntity<ApiResponse<UserDto>> registerUser(@Valid @RequestBody RegistrationDto registrationDto) {
|
||||
|
||||
UserEntity registeredUser = userService.registerNewUser(registrationDto);
|
||||
@ -50,7 +49,7 @@ public class UserController {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.success(userDto));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
@PostMapping("/api/user/login")
|
||||
public ResponseEntity<ApiResponse<Map<String, String>>> authenticateUser(@Valid @RequestBody LoginDto loginDto) {
|
||||
|
||||
Authentication authentication = authenticationManager.authenticate(
|
||||
|
@ -1,9 +1,17 @@
|
||||
package co.jp.app.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class LoginDto {
|
||||
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
@Email(message = "邮箱格式不正确,请输入有效的邮箱地址")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Size(min = 6, max = 30, message = "密码长度必须在6到30位之间")
|
||||
private String password;
|
||||
|
||||
public String getEmail() {
|
||||
|
@ -1,11 +1,26 @@
|
||||
package co.jp.app.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class RegistrationDto {
|
||||
|
||||
//注:username可以为空
|
||||
@Size(min = 2, max = 20, message = "用户名长度必须在2到20个字符之间")
|
||||
@Pattern(
|
||||
regexp = "^[a-zA-Z\\p{script=Han}]+$",
|
||||
message = "用户名只能包含大小写英文字母和汉字,不能使用数字和标点符号"
|
||||
)
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
@Email(message = "邮箱格式不正确,请输入有效的邮箱地址")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@Size(min = 6, max = 30, message = "密码长度必须在6到30位之间")
|
||||
private String password;
|
||||
|
||||
public String getName() {
|
||||
|
@ -7,7 +7,7 @@ import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "Pet")
|
||||
@Table(name = "Pet_Entity")
|
||||
public class PetEntity {
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import co.jp.app.common.ResultCode;
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
// 日志记录器
|
||||
// slf4j日志记录器
|
||||
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
// 业务异常
|
||||
|
@ -1,17 +1,12 @@
|
||||
package co.jp.app.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import co.jp.app.entity.PetEntity;
|
||||
|
||||
@Repository
|
||||
public interface DownloadRepository extends JpaRepository<PetEntity, Integer>{
|
||||
|
||||
@Override
|
||||
default List<PetEntity> findAllById(Iterable<Integer> id) {
|
||||
return findAllById(id);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,15 +2,12 @@ package co.jp.app.repository;
|
||||
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import co.jp.app.entity.ErrorEntity;
|
||||
|
||||
|
||||
@Repository
|
||||
public interface ErrRepository extends JpaRepository<ErrorEntity, Integer>{
|
||||
|
||||
public default ErrorEntity getById(@Param("id") int id) {
|
||||
|
||||
return getById(id);
|
||||
}
|
||||
}
|
@ -1,15 +1,10 @@
|
||||
package co.jp.app.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import co.jp.app.entity.PetEntity;
|
||||
|
||||
@Repository
|
||||
public interface PetRepository extends JpaRepository<PetEntity, Integer> {
|
||||
|
||||
@Override
|
||||
default List<PetEntity> findAllById(Iterable<Integer> id) {
|
||||
return findAllById(id);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,12 @@
|
||||
package co.jp.app.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import co.jp.app.entity.PetEntity;
|
||||
|
||||
@Repository
|
||||
public interface UploadRepository extends JpaRepository<PetEntity, Integer>{
|
||||
|
||||
@Override
|
||||
default <S extends PetEntity> List<S> saveAll(Iterable<S> entities) {
|
||||
// TODO 自動生成されたメソッド・スタブ
|
||||
return saveAll(entities);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,4 +14,8 @@ public interface UserRepository extends JpaRepository<UserEntity, Integer> {
|
||||
boolean existsByEmail(String email);
|
||||
|
||||
Optional<UserEntity> findByEmail(String email);
|
||||
|
||||
boolean existsByName(String name);
|
||||
|
||||
Optional<UserEntity> findByName(String name);
|
||||
}
|
@ -3,8 +3,6 @@ package co.jp.app.service;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import co.jp.app.common.ResultCode;
|
||||
import co.jp.app.exception.BusinessException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
@ -16,8 +14,10 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import co.jp.app.common.ResultCode;
|
||||
import co.jp.app.dto.RegistrationDto;
|
||||
import co.jp.app.entity.UserEntity;
|
||||
import co.jp.app.exception.BusinessException;
|
||||
import co.jp.app.repository.UserRepository;
|
||||
|
||||
@Service
|
||||
@ -31,18 +31,12 @@ public class UserService implements UserDetailsService {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserEntity registerNewUser(@NotNull RegistrationDto registrationDto) throws BusinessException {
|
||||
|
||||
if (userRepository.existsByEmail(registrationDto.getEmail())) {
|
||||
throw new BusinessException(ResultCode.USER_EMAIL_ALREADY_EXISTS,"error: Email" + registrationDto.getEmail() + " had been used");
|
||||
}
|
||||
|
||||
//密码最短6位限制
|
||||
if (registrationDto.getPassword() == null || registrationDto.getPassword().length() < 6) {
|
||||
throw new BusinessException(ResultCode.USER_PASSWORD_TOO_SHORT);
|
||||
}
|
||||
|
||||
UserEntity newUser = new UserEntity();
|
||||
newUser.setName(registrationDto.getName());
|
||||
newUser.setEmail(registrationDto.getEmail());
|
||||
|
168
src/test/java/co/jp/app/UserServiceTest.java
Normal file
168
src/test/java/co/jp/app/UserServiceTest.java
Normal file
@ -0,0 +1,168 @@
|
||||
package co.jp.app;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import co.jp.app.common.ResultCode;
|
||||
import co.jp.app.dto.RegistrationDto;
|
||||
import co.jp.app.entity.UserEntity;
|
||||
import co.jp.app.exception.BusinessException;
|
||||
import co.jp.app.repository.UserRepository;
|
||||
import co.jp.app.service.UserService;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class UserServiceTest {
|
||||
|
||||
@Mock
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@InjectMocks
|
||||
private UserService userService;
|
||||
|
||||
private RegistrationDto registrationDto;
|
||||
private UserEntity userEntity;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
registrationDto = new RegistrationDto();
|
||||
registrationDto.setName("Test User");
|
||||
registrationDto.setEmail("test@example.com");
|
||||
registrationDto.setPassword("password123");
|
||||
|
||||
userEntity = new UserEntity();
|
||||
userEntity.setName("Test User");
|
||||
userEntity.setEmail("test@example.com");
|
||||
userEntity.setPassword("encodedPassword");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("新用户注册成功")
|
||||
public void registerNewUser_success() throws BusinessException {
|
||||
// Arrange
|
||||
when(userRepository.existsByEmail(anyString())).thenReturn(false);
|
||||
when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword");
|
||||
when(userRepository.save(any(UserEntity.class))).thenReturn(userEntity);
|
||||
|
||||
// Act
|
||||
UserEntity savedUser = userService.registerNewUser(registrationDto);
|
||||
|
||||
// Assert
|
||||
assertNotNull(savedUser);
|
||||
assertEquals(userEntity.getEmail(), savedUser.getEmail());
|
||||
assertEquals("encodedPassword", savedUser.getPassword());
|
||||
verify(userRepository, times(1)).existsByEmail("test@example.com");
|
||||
verify(passwordEncoder, times(1)).encode("password123");
|
||||
verify(userRepository, times(1)).save(any(UserEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("用户注册 - 邮箱已存在")
|
||||
public void registerNewUser_emailAlreadyExists() {
|
||||
// Arrange
|
||||
when(userRepository.existsByEmail(anyString())).thenReturn(true);
|
||||
|
||||
// Act & Assert
|
||||
BusinessException exception = assertThrows(BusinessException.class, new Executable() {
|
||||
public void execute() throws Throwable {
|
||||
userService.registerNewUser(registrationDto);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(ResultCode.USER_EMAIL_ALREADY_EXISTS, exception.getResultCode());
|
||||
verify(userRepository, times(1)).existsByEmail("test@example.com");
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository, never()).save(any(UserEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("用户注册 - 密码过短")
|
||||
public void registerNewUser_passwordTooShort() {
|
||||
// Arrange
|
||||
registrationDto.setPassword("123"); // 设置一个短密码
|
||||
when(userRepository.existsByEmail(anyString())).thenReturn(false);
|
||||
|
||||
// Act & Assert
|
||||
BusinessException exception = assertThrows(BusinessException.class, new Executable() {
|
||||
public void execute() throws Throwable {
|
||||
userService.registerNewUser(registrationDto);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(ResultCode.USER_PASSWORD_TOO_SHORT, exception.getResultCode());
|
||||
verify(userRepository, times(1)).existsByEmail("test@example.com");
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository, never()).save(any(UserEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("用户注册 - 密码为null")
|
||||
public void registerNewUser_passwordIsNull() {
|
||||
// Arrange
|
||||
registrationDto.setPassword(null); // 设置密码为null
|
||||
when(userRepository.existsByEmail(anyString())).thenReturn(false);
|
||||
|
||||
// Act & Assert
|
||||
BusinessException exception = assertThrows(BusinessException.class, new Executable() {
|
||||
public void execute() throws Throwable {
|
||||
userService.registerNewUser(registrationDto);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(ResultCode.USER_PASSWORD_TOO_SHORT, exception.getResultCode());
|
||||
verify(userRepository, times(1)).existsByEmail("test@example.com");
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository, never()).save(any(UserEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("通过邮箱加载用户 - 用户存在")
|
||||
public void loadUserByUsername_userFound() {
|
||||
// Arrange
|
||||
when(userRepository.findByEmail(anyString())).thenReturn(Optional.of(userEntity));
|
||||
|
||||
// Act
|
||||
UserDetails userDetails = userService.loadUserByUsername("test@example.com");
|
||||
|
||||
// Assert
|
||||
assertNotNull(userDetails);
|
||||
assertEquals(userEntity.getEmail(), userDetails.getUsername());
|
||||
assertEquals(userEntity.getPassword(), userDetails.getPassword());
|
||||
assertTrue(userDetails.getAuthorities().stream()
|
||||
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ROLE_USER")));
|
||||
verify(userRepository, times(1)).findByEmail("test@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("通过邮箱加载用户 - 用户不存在")
|
||||
public void loadUserByUsername_userNotFound() {
|
||||
// Arrange
|
||||
when(userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
|
||||
|
||||
// Act & Assert
|
||||
UsernameNotFoundException exception = assertThrows(UsernameNotFoundException.class, new Executable() {
|
||||
public void execute() throws Throwable {
|
||||
userService.loadUserByUsername("unknown@example.com");
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals("unknown@example.com not found", exception.getMessage());
|
||||
verify(userRepository, times(1)).findByEmail("unknown@example.com");
|
||||
}
|
||||
}
|
70
src/test/java/co/jp/app/UserServiceTest1.java
Normal file
70
src/test/java/co/jp/app/UserServiceTest1.java
Normal file
@ -0,0 +1,70 @@
|
||||
package co.jp.app;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
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 org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import co.jp.app.dto.RegistrationDto;
|
||||
import co.jp.app.entity.UserEntity;
|
||||
import co.jp.app.exception.BusinessException;
|
||||
import co.jp.app.repository.UserRepository;
|
||||
import co.jp.app.service.UserService;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class UserServiceTest1 {
|
||||
|
||||
@Mock
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@InjectMocks
|
||||
private UserService userService;
|
||||
|
||||
private RegistrationDto registrationDto;
|
||||
private UserEntity userEntity;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
registrationDto = new RegistrationDto();
|
||||
registrationDto.setName("Test User");
|
||||
registrationDto.setEmail("test@example.com");
|
||||
registrationDto.setPassword("password123");
|
||||
|
||||
userEntity = new UserEntity();
|
||||
userEntity.setName("Test User");
|
||||
userEntity.setEmail("test@example.com");
|
||||
userEntity.setPassword("encodedPassword");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("新用户注册成功")
|
||||
public void registerNewUser_success() throws BusinessException {
|
||||
// Arrange
|
||||
when(userRepository.existsByEmail(anyString())).thenReturn(false);
|
||||
when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword");
|
||||
when(userRepository.save(any(UserEntity.class))).thenReturn(userEntity);
|
||||
|
||||
// Act
|
||||
UserEntity savedUser = userService.registerNewUser(registrationDto);
|
||||
|
||||
// Assert
|
||||
assertNotNull(savedUser);
|
||||
assertEquals(userEntity.getEmail(), savedUser.getEmail());
|
||||
assertEquals("encodedPassword", savedUser.getPassword());
|
||||
verify(userRepository, times(1)).existsByEmail("test@example.com");
|
||||
verify(passwordEncoder, times(1)).encode("password123");
|
||||
verify(userRepository, times(1)).save(any(UserEntity.class));
|
||||
}
|
||||
|
||||
}
|
2
target/classes/.gitignore
vendored
2
target/classes/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
/META-INF/
|
||||
/co/
|
@ -1,7 +0,0 @@
|
||||
#Generated by Maven Integration for Eclipse
|
||||
#Wed May 14 11:48:45 JST 2025
|
||||
m2e.projectLocation=C\:\\Users\\ichbi\\OneDrive\\\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\\dog-1
|
||||
m2e.projectName=dog-1
|
||||
groupId=co.jp.app
|
||||
artifactId=dog-2
|
||||
version=0.0.1-SNAPSHOT
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest$1.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest$1.class
Normal file
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest$2.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest$2.class
Normal file
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest$3.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest$3.class
Normal file
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest$4.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest$4.class
Normal file
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest.class
Normal file
Binary file not shown.
BIN
target/test-classes/co/jp/app/UserServiceTest1.class
Normal file
BIN
target/test-classes/co/jp/app/UserServiceTest1.class
Normal file
Binary file not shown.
Reference in New Issue
Block a user