[wisestudy] Domain 삽입/조회 테스트

getch_·2020년 6월 15일
0

ToyProject

목록 보기
4/5

JPA를 사용한 도메인 객체 삽입/조회 테스트

이전 포스트에 이어 Spring Boot에서 JPA/Hibernate를 사용하여 도메인 객체를 삽입하고, 조회하는 테스트를 진행합니다.

도메인 객체는 이전 포스트에서 생성한 User 객체를 사용합니다.
User API를 작성하여, 웹 기반으로 데이터 삽입, 조회 기능을 구현합니다.

Table of Contents

  • Repository 생성
  • Service 생성
  • Controller 생성
  • JSON 응답을 위한 환경 설정
  • API 테스트

Repository 생성

  • 샘플 코드
@Repository
public interface UserRepository extends JpaRepository<User, String> {
    List<User> findAll();
    User findById(Long id);
    User save(User user);
}
  • @Repository: Repository 빈으로 등록될 수 있도록 지정
  • JpaRepository: JPA 레포지토리를 상속받아 사용
  • findAll(), findByName(), save()
    • 메서드 이름을 기반으로 Query를 실행할 수 있도록 하는 Interface 메서드 상속

Service 생성

  • 샘플 코드
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public List<User> retrieveAllUser() {
        return userRepository.findAll();
    }
    
    public User retrieveUser(Long userId) {
        return userRepository.findById(userId);
    }

    public User registerUser(User user) {
        return userRepository.save(user);
    }
}
  • @Service: Service 빈으로 등록될 수 있도록 지정
  • @Autowired: 빈 등록된 객체 주입
  • retrieveAllUser(), registerUser()
    • Repository를 사용하는 로직 구현

Controller 생성

  • 샘플 코드
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping(value="")
    public List<User> getAllUsers() {
        return userService.retrieveAllUsers();
    }

    @GetMapping(value="/{user_id}")
    public User getUser(@PathVariable("user_id") Long userId) {
        return userService.retrieveUser(userId);
    }
    
    @PostMapping(value="")
    public User createUser(@RequestBody User user) {
        return userService.registerUser(user);
    }
}
  • @RestController: Controller 빈으로 등록될 수 있도록 지정
    • @RestController를 사용 시 각 메서드의 응답이 자동으로 @ResponseBody가 적용되어 View가 아닌 HTTP Body로 응답
  • @RequestMapping: 요청을 받을 URL 경로를 설정
  • @GetMapping, @PostMapping: @RequestMapping를 대체하여, Method가 적용되어 있는 URL Mapping Annotation
  • @PathVariable: URL 경로로 전달된 값을 사용하기 위한 Annotation

JSON 응답을 위한 환경 설정

Spring Boot에서는 spring-boot-starter-web을 사용하면 Jackson 라이브러리가 기본 포함되어 있습니다.
또한, 대부분의 환경 설정은 코드로 구현됩니다.

1. Jackson 라이브러리의 환경 설정 코드 구현

  • JacksonConfigurer(환경 설정) 클래스
@Configuration
public class JacksonConfigurer {

    @Bean
    public ObjectMapper objectMapper() {
        return Jackson2ObjectMapperBuilder.json()
                .modules(new JavaTimeModule())
                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .featuresToEnable(SerializationFeature.WRAP_ROOT_VALUE)
                .featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
                .build();
    }

}
  • @Configuration: Spring boot 실행 시 환경 설정에 사용될 수 있도록 지정
  • JavaTimeModule(): 자바 시간 모듈 추가
  • PropertyNamingStrategy.SNAKE_CASE: 객체->JSON 변환 시 camelCase를 snake_case로 변환
    • JSON->객체 변환 시에는 반대
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS: Datetime 기록시 Epoch 시간으로 기록되는 기능 해제
  • SerializationFeature.WRAP_ROOT_VALUE: 도메인 클래스 이름을 JSON 객체의 root 이름으로 사용하도록 설정
  • MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS: Enum 타입의 필드 값에 대해서 대/소문자 구분하지 않도록 설정

2. JSON 응답을 위한 도메인 클래스 수정

  • 수정된 클래스
@Entity
@Table
@Getter
@Setter
@JsonPropertyOrder({
        "id",
        "email",
        "password",
        "name",
        "birth",
        "cellPhone",
        "gender"
})
@JsonRootName("user")
public class User {

    @Id
    @Column(name = "user_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonProperty("user_id")
    private Long id;

    @Column(nullable = false, length = 50)
    private String email;

    @Column(nullable = false, length = 20)
    private String password;

    @Column(nullable = false, length = 20)
    private String name;

    @Column(name = "birthday")
    @JsonProperty("birthday")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate birth;

    @Column(name = "cell_phone", nullable = false, length = 20)
    private String cellPhone;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, columnDefinition = "enum('FEMALE', 'MALE')")
    private Gender gender;
}
  • @JsonPropertyOrder: JSON 변환 시 출력될 프로퍼티 순서 지정
  • @JsonRootName: JSON 객체의 root 이름 지정
  • @JsonProperty: 필드명 대신 출력할 프로퍼티 이름 지정
  • @JsonFormat: JSON 값을 받거나, 출력할 때 Date 타입에 대한 포멧 지정

3. List 대신 @JsonRootName을 사용하기 위한 클래스 구현

  • ArrayList를 상속 받는 클래스
@JsonRootName("users")
public class Users extends ArrayList<User> {
}
  • 위와 같은 빈 클래스를 생성 후, Repository, Service, Controller에서 아래의 내용 변경
    • List<User> -> Users로 반환 값 변경

API 테스트

API 클라이언트 도구인 Postman을 사용하여 테스트 하였습니다.
샘플로 삽입된 cURL 코드를 사용하면 Postman에 바로 삽입할 수 있습니다.

  1. 데이터 삽입 테스트
  • Request
curl -X POST http://localhost:8080/api/v1/users \
-H 'Content-type':'application/json' \
-d \
'{
    "name": "graceful",
    "email": "grace@wisestudy.com",
    "password": "temp",
    "birthday": "2020-06-16",
    "cell_phone": "010-0001-0001",
    "gender": "female"
}'
  • Response
  1. 데이터 조회 테스트
  • Request
curl -X GET http://localhost:8080/api/v1/users \
-H 'Content-type':'application/json'
  • Response
    • 초기 더미 데이터와 삽입된 데이터를 확인할 수 있음
    • 형광펜 강조한 부분은 JSON 설정으로 인해 기본 출력 값과 변경된 부분

참고

profile
한꺼번에 몰아치지 아니하고 오래도록.

0개의 댓글