//request
public record UserRequest(
String userName,
String userInfoId,
String userPassword,
String userEmail
) {
}
//response
public record UserResponse(
Long id,
String userName,
String userId,
String userPassword,
String userEmail
) {
}
//request - 이름 조회용 요청
public record UserProfileRequest(
Long id,
String userName
) {
}
//response - 이름 조회용 응답
public record UserProfileResponse(
Long id,
String userName
) {
}
@RestController
public class UserInfoController {
private final UserService userService;
public UserInfoController(UserService userService) {
this.userService = userService;
}
@PostMapping("/users/infos")
public UserResponse save(@Valid @RequestBody UserRequest userRequest){
return userService.save(userRequest);
}
//사용자의 프로필 - 이름만 보이는 상태
@GetMapping("/users")
public UserProfileResponse findById(@Valid @RequestBody UserProfileRequest userProfileRequest){
return userService.findByProfile(userProfileRequest);
}
//사용자의 프로필 조회 - 아이디/비번
@GetMapping("/users/profiles")
public UserResponse findByUserProfile(@RequestParam Long userId){
return userService.findByUserProfileDetail(userId);
}
@PutMapping("/users/{userId}")
public UserResponse update(@PathVariable Long userId, @Valid @RequestBody UserRequest userRequest){
return userService.update(userId, userRequest);
}
@DeleteMapping("/users/{userId}")
public void delete(@PathVariable Long userId){
userService.deleteById(userId);
}
}
public interface UserRepository extends JpaRepository<UserInfo, Long> {
}
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public UserResponse save(UserRequest userRequest) {
UserInfo user = userRepository.save(new UserInfo(
userRequest.userName(),
userRequest.userInfoId(),
userRequest.userPassword(),
userRequest.userEmail()));
return new UserResponse(
user.getId(),
user.getUserName(),
user.getUserId(),
user.getPassWord(),
user.getEmail());
}
public UserResponse findByUserProfileDetail(Long userId) {
UserInfo user = userRepository.findById(userId)
.orElseThrow(() -> new NoSuchElementException("찾는 사용자가 없습니다."));
return new UserResponse(
userId,
user.getUserName(),
user.getUserId(),
user.getPassWord(),
user.getEmail()
);
}
public UserProfileResponse findByProfile(UserProfileRequest userProfileRequest) {
userRepository.findById(userProfileRequest.id())
.orElseThrow(() -> new NoSuchElementException("찾는 사용자가 없습니다."));
return new UserProfileResponse(userProfileRequest.id(), userProfileRequest.userName());
}
@Transactional
public UserResponse update(Long userId, UserRequest userRequest) {
UserInfo user = userRepository.findById(userId)
.orElseThrow(() -> new NoSuchElementException("찾는 사용자가 없습니다"));
user.setUserId(userRequest.userInfoId());
user.setUserName(userRequest.userName());
user.setPassWord(userRequest.userPassword());
user.setEmail(userRequest.userEmail());
return new UserResponse(
userId,
userRequest.getUserName(),
userRequest.getUserId(),
userRequest.getPassWord(),
userRequest.getEmail());
}
public void deleteById(Long userId) {
userRepository.findById(userId)
.orElseThrow(()->new NoSuchElementException("찾는 사용자가 없습니다."));
userRepository.deleteById(userId);
}
}
@Entity
public class UserInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String userName;
private String userId;
private String passWord;
private String email;
protected UserInfo() {
}
public UserInfo(String userName, String userId, String passWord, String email) {
this.userName = userName;
this.userId = userId;
this.passWord = passWord;
this.email = email;
}
public Long getId() {
return id;
}
public String getUserName() {
return userName;
}
public String getUserId() {
return userId;
}
public String getPassWord() {
return passWord;
}
public String getEmail() {
return email;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setUserId(String userId) {
this.userId = userId;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public void setEmail(String email) {
this.email = email;
}
}
Test 코드 작성하기
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserTest extends AcceptanceTest {
@LocalServerPort
int port;
@BeforeEach
void setUp() {
RestAssured.port = port;
}
@Test
void 사용자_생성() {
UserResponse 사용자1 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "123", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
assertThat(사용자1).isNotNull();
}
@Test
void 사용자_프로필조회_이름만조회() {
UserResponse 사용자1 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "123", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
UserResponse 추민영 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserProfileRequest(사용자1.id(), 사용자1.userName()))
.when()
.get("/users")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
assertThat(추민영.userName()).isNotNull();
}
@Test
void 사용자정보_전체조회() {
UserResponse 사용자1 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "123", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
UserResponse 사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.queryParam("userId",사용자1.id())
.when()
.get("/users/profiles")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
assertThat(사용자.userId()).isEqualTo(사용자1.userId());
assertThat(사용자.userName()).isEqualTo(사용자1.userName());
assertThat(사용자.userPassword()).isEqualTo(사용자1.userPassword());
}
@Test
void 사용자정보_수정() {
String userName = "수정 전 이름";
String updatedUserName = "수정 후 이름";
UserResponse 수정전사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest(userName, "chuchu", "123", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
UserResponse 수정후사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.pathParam("userId", 수정전사용자.id())
.body(new UserRequest(updatedUserName, "chuchu", "123", "chu@naver.com"))
.when()
.put("/users/{userId}")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
UserResponse 사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.queryParam("userId", 수정후사용자.id())
.when()
.get("/users/profiles")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
assertThat(사용자.userName()).isEqualTo(updatedUserName);
}
@Test
void 사용자정보_삭제() {
UserResponse 삭제전사용자 = RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.body(new UserRequest("추민영", "chuchu", "123", "chu@naver.com"))
.when()
.post("/users/infos")
.then().log().all()
.statusCode(200)
.extract()
.as(UserResponse.class);
RestAssured
.given().log().all()
.contentType(ContentType.JSON)
.pathParam("userId", 삭제전사용자.id())
.when()
.delete("/users/{userId}")
.then().log().all()
.statusCode(200);
}
}
😐 느낀점
API Spec을 작성하고나면 나머지 API 구현하는 일은 쉽다.
기본적인 API구현은 (CRUD) 잘 작성하기!