티스토리 뷰
안녕하세요 강정호 입니다.
이번에는 게시글 서비스를 테스트하는 로직을 구현해보려고 합니다.
ArticleServiceTest 코드
package com.marathon.board.service;
import java.util.List;
import com.marathon.board.domain.type.SearchType;
import com.marathon.board.dto.ArticleDto;
import com.marathon.board.repository.ArticleRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
@DisplayName("게시글 테스트")
@SpringBootTest
@ExtendWith(MockitoExtension.class)
public class ArticleServiceTest {
@InjectMocks private ArticleService sut;
@Mock private ArticleRepository articleRepository;
@DisplayName("게시글을 검색하면, 게시글 리스트를 반환한다.")
@Test
void givenSearchParameters_whenSearchingArticles_thenReturnArticleLists(){
// Given
//SearchParameters searchParameters = SearchParameters.of();
// When
Page<ArticleDto> articles = sut.searchArticles(SearchType.TITLE, "search keyword");
// Then
Assertions.assertThat(articles).isNotNull();
}
@DisplayName("게시글을 조회하면, 게시글을 반환한다.")
@Test
void givenArticleId_whenSearchingArticle_thenReturnArticle(){
// Given
//SearchParameters searchParameters = SearchParameters.of();
// When
ArticleDto articles = sut.searchArticle(1L);
// Then
Assertions.assertThat(articles).isNotNull();
}
}
@SpringBootTest
단위테스트와 같은 검증이 아닌 스프링에서 실제 운영환경과 같이 전체 플로우가 잘 동작하는지 확인하기 위한
통합테스트이다. SpringBootTest는 실행시 SpringBootApplication을 사용하여 모든 빈을 등록한다.
그렇다보니 테스트 소요시간이 길고 메모리를 많이 사용하게 된다.
@InjectMock과 @Mock의 차이
@Mock 어노테이션은 목 객체를 생성하는 데 사용됩니다. 이 어노테이션을 사용하면 해당 필드에 대한 목 객체가 자동으로 생성됩니다. @Mock 어노테이션이 붙은 필드는 테스트할 객체에서 의존성으로 사용되는 객체를 목 객체로 대체할 수 있습니다. 이렇게 하면 해당 필드에 대한 목 객체를 직접 생성하고 관리할 필요가 없습니다.
@Mock으로 ArticleRepository를 생성한다.
@InjectMocks 어노테이션은 ArticleService 클래스의 인스턴스를 생성하면서 @Mock 어노테이션으로 생성된 목 객체를 해당 필드에 주입(inject)합니다. 이렇게 함으로써 ArticleService 객체는 목 객체가 주입된 상태로 생성됩니다.
위의 2가지 테스트는 다음을 테스트합니다.
1) 제목으로 게시글을 검색하면 게시글 리스트를 반환하는지 여부
2) 특정 게시글을 게시글 아이디로 조회하면, 해당 게시글을 반환하는지 여부
위 테스트를 진행하기 위한 ArticleService 코드는 다음과 같습니다.
package com.marathon.board.service;
import java.time.LocalDateTime;
import java.util.List;
import com.marathon.board.domain.type.SearchType;
import com.marathon.board.dto.ArticleDto;
import com.marathon.board.repository.ArticleRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Transactional
@Service
public class ArticleService {
private final ArticleRepository articleRepository;
@Transactional(readOnly = true)
public Page<ArticleDto> searchArticles(SearchType title, String searchKeyword) {
// Page 안에 이미 페이지네이션 구현이 되어있다.
return Page.empty();
}
@Transactional(readOnly = true)
public ArticleDto searchArticle(long l) {
return null;
}
}
@Transactional 어노테이션
DB의 데이터무결성, 동시성 제어, 예외처리 등을 보장하고 여러개의 논리적 연산을 하나의 묶음으로 처리하기 위해서 @Transactional 어노테이션을 사용한다. Article을 생성, 갱신, 삭제 등을 할 때 1개의 트랜잭션으로 묶어주어 데이터의 일관성 유지.
메서드에 @Transactional(readOnly = true)를 사용하면 좋은 점
- 성능 향상: readOnly 속성을 true로 설정하면 트랜잭션 동안 변경 작업을 수행하지 않음을 알리므로, 데이터베이스의 락을 획득하지 않고 읽기 작업을 수행할 수 있습니다. 이는 성능 향상을 가져올 수 있습니다. 변경 작업이 필요하지 않은 읽기 전용 트랜잭션에서는 데이터베이스의 일관성을 유지하기 위해 록을 사용할 필요가 없습니다.
- 동시성 제어: 읽기 전용 트랜잭션은 동시에 여러 개의 트랜잭션에서 접근할 수 있습니다. 따라서 동시성 문제를 줄이고, 다중 스레드 환경에서 안전하게 작업할 수 있습니다. 반면에 읽기와 쓰기 작업을 함께 하는 트랜잭션에서는 록 충돌이 발생할 수 있으며, 이는 성능 저하와 동시성 문제를 야기할 수 있습니다.
- 데이터 무결성 보장: 읽기 전용 트랜잭션에서는 데이터를 수정하지 않기 때문에 데이터 무결성이 보장됩니다. 읽기 작업만 필요한 메서드에서는 readOnly 속성을 사용하여 실수로 데이터를 수정하는 문제를 방지할 수 있습니다.
- 코드 의도 명확화: @Transactional(readOnly = true)를 사용함으로써 해당 메서드가 읽기 작업에만 사용되는 것임을 명확하게 표현할 수 있습니다. 다른 개발자들이 코드를 이해하고 유지보수하는 데 도움이 됩니다.
'Back-end' 카테고리의 다른 글
[프로젝트] 게시판 뷰 페이지 만들기(Thymleaf, ArticleController) (0) | 2023.06.04 |
---|---|
[게시판 만들기] 추가해야 할 코드 (0) | 2023.05.14 |
[게시판 개발하기] 뷰 만들기 (0) | 2023.05.08 |
[게시판 만들기] rebase merge (0) | 2023.05.07 |
09. 게시글 페이지 만들기 (0) | 2023.04.05 |
- Total
- Today
- Yesterday
- Inception
- 관계대수
- ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
- github
- front
- 깃허브
- 깃
- 항해플러스백엔드
- Use case
- 부동산공부
- 인셉션
- 도커
- push_back
- 월급쟁이부자들
- 월부닷컴
- Spring boot
- 폭포수
- 유즈케이스
- 항해솔직후기
- 2023년
- docker
- 열반스쿨기초반
- GIT
- 재테크공부
- 파라메터
- 개발자 회고
- resize
- pop_back
- 항해플러스후기
- 내년은 빡세게!!
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |