[CowAPI] 2-1. TDD Code review

준돌·2022년 5월 28일
0

오늘의 Cow

목록 보기
3/45
post-thumbnail

1. TDD


  • 블로그 하나에 다 정리하여 넣기에는 양이 많아 코드 리뷰와 분리했습니다.

2. 구조


  • 각 테스트 들은 ServerApplicationTest를 부모로 갖습니다.
    😎 공통으로 사용하게 될 코드를 ServerApplicationTest에서 상속받기 위해 사용합니다.

  • 모든 기능마다 DomainTest, ServiceTest, ControllerTest, IntegrantionTest를 진행합니다.

  • Feature의 각 테스트들은 필요한 어노테이션과 함수를 상속받습니다.
    😎 각 테스트 마다 사용되는 어노테이션과 함수가 다르기 때문입니다.


3. Domain Test


@DataJpaTest

  • 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만을 테스트 하기 위해 사용합니다.

@Transactional(propagation = Propagation.NOT_SUPPORTED)

  • 현재의 transaction을 잠시 중단하고 logic을 transaction 없이 수행합니다.

😎 insert SQL문을 실행했을 때, Spring-Boot는 DB의 Cache를 먼저 확인하기 때문에 Select을 수행하고 성공하게 되면 insert를 실행하지 않습니다. insert 문을 테스트 하기 위해 사용합니다.

@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)

  • DataJpaTest의 어노테이션입니다.
  • application-defined or auto-configure DataSource 대신에 test database를 정의합니다.

😎 application DB와 test DB가 다르기 때문에 로컬에 있는 test DB인 mysql을 사용하기 위해 사용합니다.


4. Service Test


@ExtendWith(MockitoExtension.class)

  • mocks을 초기화하고 strict stub을 handling합니다.

😎 Repository를 Mock으로 사용하고 stub을 생성 하기 위해 사용합니다.

@InjectMocks

  • constructor injection, property injection or setter injection을 통해 Mock을 주입하기 위해 사용합니다.
  • @InjectMocks는 @Spy or @Mock 어노테이션만을 사용해서 주입합니다.

😎 Mock 객체인 Repository을 Service에 주입하기 위해 사용합니다.

@Mock

  • 반복되는 mock 생성 코드를 최소화합니다.
  • 테스트 클래스를 더 읽기 쉽게 만듭니다.
  • mock을 식별하는데 수월해집니다.

😎 Domain과 Service를 고립하기 위해 Repository를 Mock으로 사용합니다.


5. Controller Test


@WebMvcTest(UserController.class)

  • Spring MVC test를 위한 어노테이션입니다.
  • 이 어노테이션을 사용하면 auto-configuration이 비활성되고 MVC 테스트와 관련된 구성만 적용됩니다.
  • @Component, @Service, @Repository bean 들은 비활성됩니다.

😎 Domain, Service와 Controller를 고립시키기 위해 사용합니다. 여기서는 예제로 UserController 클래스만을 사용합니다.

@MockBean

  • Spring Application Context에 모크를 추가할 수 있게 해주는 어노테이션입니다.
  • Mock들은 type이나 bean name으로 등록할 수 있습니다.
  • type이 등록되면 subclasses를 포함하여 context에 존재하는 single bean들을 mock으로 대체합니다.

😎 Controller에서 context가 들어오면 Service, Domain을 mock으로 대체합니다.


6. Integration Test


@Transactional

  • 각각의 method나 class에 대한 트랜잭션 특징을 설명합니다.

  • 클래스 수준에서 선언이 되면 선언 클래스와 하위 클래스의 모든 method에 기본값으로 적용됩니다.

  • custom rollback 규칙이 없을 경우, 트랜잭션은 exceptions을 확인하지 않고 RuntimeException과 Error에서만 roll back을 수행합니다.

  • Rollback 규칙은 rollbackFor()/noRollbackFor() 그리고 rollbackForClassName()/noRollbackForClassName()로 정의될 수 있습니다.

  • SpringDataJpa를 살펴보면 @Transactional(readOnly = true) 을 볼 수 있습니다.

  • readOnly를 설정해 주면 runtime에 읽기전용으로 최적화됩니다.

😎 Test 실행 이후 rollback 하기 위해 사용합니다.

@AutoConfigureMockMvc

  • 테스트 클래스에서 MockMvc를 사용하고 auto-configuration 하기 위해 사용합니다.

😎 MockMvc를 사용하기 위해 사용합니다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

  • 특정 @ContextConfiguration(loader=...)가 정의되지 않을경우 SpringBootContextLoader를 default ContextLoader로 사용합니다.
  • @Configuration을 사용하지 않고 명시적으로 클래스를 지정하지 않을 경우 @SpringBootConfiguration 을 자동적으로 찾습니다.
  • properties attribute를 사용하여 custom Environment properties를 정의할 수 있습니다.
  • 다른 webEnvironment mode를 지원합니다.

😎 Server를 실행하고 @LocalServerPort 주입 필드와 함께 사용하기 위해 사용합니다.

@LocalServerPort

  • 런타임에 할당된 HTTP 포트를 주입하는 어노테이션입니다.
  • @Value("${local.server.port}")를 편리하게 제공합니다.

😎 random port를 주입 받기 위해 사용합니다.


7. Test Code


  • 각 기능에 대한 테스트 코드는 Github에서 확인하실 수 있습니다.
  • Github : CowAPI

profile
눈 내리는 겨울이 좋아!

0개의 댓글