Representational State Transfer
json, xml …. 와 같이 자원 (Resources)을 하나의 표현식으로 나타내는 것클라이언트와 서버 간의 자원의 상태 를 의미HTTP Protocol 을 통해서 데이터를 전달받고, 전송한다. → 자원은 URI 로 식별된다.자원을 식별 하는 문자열 = 고유한 이름 = 고유한 경로2가지로 나뉠 수 있다.
자원의 이름을 식별 → 자원 자체를 고유로 식별
자원의 위치를 식별 → 자원에 어떻게 접근할지를 설명
URL은 자원의 위치를 명시하는 URI 의 일종
URL은 자원이 위치한 프로토콜, 호스트, 경로 등의 정보를 제공
[Example]
https://www.example.com/index.html
https는 프로토콜
www.example.com은 호스트명
/index.html은 경로
→ URL은 자원의 위치와 접근 방법(HTTP, FTP 등)을 함께 명시
---
Dirty CheckingUPDATE 쿼리를 작성할 필요 없이, 엔티티의 상태 변화 만으로 데이터베이스에 변경사항 적용 가능update 를 어플리케이션에서 구현flush()가 호출될 때, JPA는 엔티티의 스냅샷과 현재 상태를 비교UPDATE 쿼리를 생성하여 데이터베이스에 반영save() 내부 구조 보기→ SimpleJpaRepository.class 에 명시된 내용을 확인하자.
@Transactional
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (this.entityInformation.isNew(entity)) {
this.entityManager.persist(entity);
return entity;
} else {
return this.entityManager.merge(entity);
}
}
@Transactional 어노테이션이 붙은 것을 볼 수 있다. → @Transactional 어노테이션이 붙으면 메서드 내에 작업이 끝날 경우, flush() 메소드를 실행한다. → 이 과정에서 변경사항이 감지되면, 데이터베이스의 레코드를 업데이트 하는 쿼리가 실행된다.동등성 (Equality)동일성 (Identity)Given - When - Then 패턴Behavior Driven Development (행위 주도 개발) 을 통해 탄생한 테스트 접근 방식 → 테스트 코드가 ‘명세’ 역할을 할 수 있다는 점에서 장점!F.I.R.S.T 전략Fast [빠르게]Isolated [독립적]Repeatable [반복 가능한]Self-Validation [자가 검증]Timely [적시에]Mock 객체Mock 객체를 사용하는 이유?외부 요인 없이 테스트가 수행되어야 한다. 를 만족시켜야 한다. → 따라서, 외부 요인 을 Mock 처리하여 수행@WebMvcTest(테스트 대상 클래스.class)@Controller, @RestController, @ControllerAdvice 등의 컨트롤러 관련 빈 객체가 모두 로드됨@SpringBootTest 보다 가볍게 테스트하기 위해 사용됨@MockBeanMockito의 given() 메서드를 통해 동작을 정의해야 함@WebMvcTest(UserController.class) // Controller 단위 테스트
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService; // Service 계층 Mocking
@Test
public void getUserById_ReturnsUser() throws Exception {
// Given
User user = new User(1L, "John Doe");
Mockito.when(userService.getUserById(1L)).thenReturn(user);
// When & Then
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("John Doe"))
.andDo(print());
// Verify
Mockito.verify(userService, Mockito.times(1)).getUserById(anyLong());
}
}
perform() : 서버로 URL 요청을 보내는 것처럼 통신 테스트 코드 작성 가능 → 리턴값(결과값)으로 ResultActions 객체가 리턴된다.andExpect() : ResultActions 객체에 대한 결과값 검증을 수행할 수 있다. → ResultMatcher 를 활용andDo() : 요청과 응답의 전체 내용을 확인verify() : 지정된 메서드가 실행됐는지 검증 → given()에 정의된 동작과 대응@MockBean 과 Mockito.mock()| 사용 방법 | @MockBean | Mockito.mock() |
|---|---|---|
| Spring 통합 | Spring 컨텍스트 내에서 Mock 객체 사용 | Spring과 무관하게 독립적인 단위 테스트 가능 |
| 테스트 속도 | 상대적으로 느림 | 빠르고 가벼움 |
| 의존성 주입 | 자동으로 주입 (DI) | 직접 객체 생성 후 주입 필요 |
| 용도 | Spring MVC, 통합 테스트 | 단순한 단위 테스트 |
| 추천 사용 예시 | @WebMvcTest, @SpringBootTest 등에서 사용 | 독립적인 비즈니스 로직 단위 테스트 시 사용 |
@MockBean
private UserService userService; // MockBean 사용
private UserService userService = Mockito.mock(UserService.class); // Mockito 사용
@DataJpaTest 어노테이션Repository 단을 테스트 할 때 붙이는 어노테이션@Transactional 이 포함되어있어, 테스트 코드가 종료되면 자동적으로 DB 롤백 → 데이터베이스에 영향을 주지 않으므로 안전한 테스트가 가능
총 3개의 단계로 개발 주기를 표현
실패 테스트 작성: 실패하는 경우의 테스트 코드를 먼저 작성테스트를 통과하는 코드 작성: 테스트 코드를 성공시키기 위한 실제 코드 작성리팩토링: 중복 코드를 제거하거나 일반화하는 리팩토링 수행
설계 → 어플리케이션 코드 → 테스트 코드 순서설계 → 테스트 코드 → 어플리케이션 코드 순서