1. TDD
- 블로그 하나에 다 정리하여 넣기에는 양이 많아 코드 리뷰와 분리했습니다.
2. 구조
-
각 테스트 들은 ServerApplicationTest를 부모로 갖습니다.
😎 공통으로 사용하게 될 코드를 ServerApplicationTest에서 상속받기 위해 사용합니다.
-
모든 기능마다 DomainTest, ServiceTest, ControllerTest, IntegrantionTest를 진행합니다.
-
Feature의 각 테스트들은 필요한 어노테이션과 함수를 상속받습니다.
😎 각 테스트 마다 사용되는 어노테이션과 함수가 다르기 때문입니다.
3. Domain Test
- JPA conponent들에 집중해서 테스트하기 위핸 JPA test 어노테이션 입니다.
- @DataJpaTest 는 default로 transactional 어노테이션 되었고 각각의 테스트 끝에 roll back을 합니다.
- embedded in-memory database를 사용합니다.
- application property로 spring.jpa.show-sql을 true로 설정하면 SQL 쿼리들을 볼 수 있습니다.
😎 Controller, Serivce와 Domain을 고립시켜서 Domain만을 테스트 하기 위해 사용합니다.
- 현재의 transaction을 잠시 중단하고 logic을 transaction 없이 수행합니다.
😎 insert SQL문을 실행했을 때, Spring-Boot는 DB의 Cache를 먼저 확인하기 때문에 Select을 수행하고 성공하게 되면 insert를 실행하지 않습니다. insert 문을 테스트 하기 위해 사용합니다.
- DataJpaTest의 어노테이션입니다.
- application-defined or auto-configure DataSource 대신에 test database를 정의합니다.
😎 application DB와 test DB가 다르기 때문에 로컬에 있는 test DB인 mysql을 사용하기 위해 사용합니다.
4. Service Test
- mocks을 초기화하고 strict stub을 handling합니다.
😎 Repository를 Mock으로 사용하고 stub을 생성 하기 위해 사용합니다.
- constructor injection, property injection or setter injection을 통해 Mock을 주입하기 위해 사용합니다.
- @InjectMocks는 @Spy or @Mock 어노테이션만을 사용해서 주입합니다.
😎 Mock 객체인 Repository을 Service에 주입하기 위해 사용합니다.
- 반복되는 mock 생성 코드를 최소화합니다.
- 테스트 클래스를 더 읽기 쉽게 만듭니다.
- mock을 식별하는데 수월해집니다.
😎 Domain과 Service를 고립하기 위해 Repository를 Mock으로 사용합니다.
5. Controller Test
- Spring MVC test를 위한 어노테이션입니다.
- 이 어노테이션을 사용하면 auto-configuration이 비활성되고 MVC 테스트와 관련된 구성만 적용됩니다.
- @Component, @Service, @Repository bean 들은 비활성됩니다.
😎 Domain, Service와 Controller를 고립시키기 위해 사용합니다. 여기서는 예제로 UserController 클래스만을 사용합니다.
- Spring Application Context에 모크를 추가할 수 있게 해주는 어노테이션입니다.
- Mock들은 type이나 bean name으로 등록할 수 있습니다.
- type이 등록되면 subclasses를 포함하여 context에 존재하는 single bean들을 mock으로 대체합니다.
😎 Controller에서 context가 들어오면 Service, Domain을 mock으로 대체합니다.
6. Integration Test
-
각각의 method나 class에 대한 트랜잭션 특징을 설명합니다.
-
클래스 수준에서 선언이 되면 선언 클래스와 하위 클래스의 모든 method에 기본값으로 적용됩니다.
-
custom rollback 규칙이 없을 경우, 트랜잭션은 exceptions을 확인하지 않고 RuntimeException과 Error에서만 roll back을 수행합니다.
-
Rollback 규칙은 rollbackFor()/noRollbackFor() 그리고 rollbackForClassName()/noRollbackForClassName()로 정의될 수 있습니다.
-
SpringDataJpa를 살펴보면 @Transactional(readOnly = true)
을 볼 수 있습니다.
-
readOnly를 설정해 주면 runtime에 읽기전용으로 최적화됩니다.
😎 Test 실행 이후 rollback 하기 위해 사용합니다.
- 테스트 클래스에서 MockMvc를 사용하고 auto-configuration 하기 위해 사용합니다.
😎 MockMvc를 사용하기 위해 사용합니다.
- 특정 @ContextConfiguration(loader=...)가 정의되지 않을경우 SpringBootContextLoader를 default ContextLoader로 사용합니다.
- @Configuration을 사용하지 않고 명시적으로 클래스를 지정하지 않을 경우 @SpringBootConfiguration 을 자동적으로 찾습니다.
- properties attribute를 사용하여 custom Environment properties를 정의할 수 있습니다.
- 다른 webEnvironment mode를 지원합니다.
😎 Server를 실행하고 @LocalServerPort 주입 필드와 함께 사용하기 위해 사용합니다.
- 런타임에 할당된 HTTP 포트를 주입하는 어노테이션입니다.
- @Value("${local.server.port}")를 편리하게 제공합니다.
😎 random port를 주입 받기 위해 사용합니다.
7. Test Code
- 각 기능에 대한 테스트 코드는 Github에서 확인하실 수 있습니다.
- Github : CowAPI