importstaticorg.assertj.core.api.Assertions.*;// 기본 동등 비교assertThat(post.getTitle()).isEqualTo("Spring Boot 입문");assertThat(post.getId()).isNotNull();assertThat(post.getStatus()).isEqualTo("PUBLISHED");// 숫자 비교assertThat(post.getViewCount()).isGreaterThan(0);assertThat(post.getViewCount()).isBetween(1,1000);assertThat(score).isCloseTo(3.14,offset(0.01));// BooleanassertThat(post.isPublished()).isTrue();assertThat(post.isDeleted()).isFalse();// Null 체크assertThat(result).isNull();assertThat(result).isNotNull();// 문자열assertThat(title).contains("Spring");assertThat(title).startsWith("Spring").endsWith("Boot");assertThat(title).hasSize(14);assertThat(slug).matches("[a-z0-9-]+");// 정규식 패턴
List<Post> posts = postService.findAll();// 크기assertThat(posts).hasSize(3);assertThat(posts).isNotEmpty();assertThat(posts).isEmpty();// 포함 여부assertThat(posts).contains(post1, post2);assertThat(posts).containsExactly(post1, post2, post3);// 순서까지 일치assertThat(posts).containsExactlyInAnyOrder(post3, post1, post2);// 순서 무관// 특정 필드 추출 후 검증assertThat(posts).extracting("title").containsExactly("제목1","제목2","제목3");// 여러 필드 동시 검증assertThat(posts).extracting("title","status").containsExactly(tuple("제목1","PUBLISHED"),tuple("제목2","DRAFT"));// 조건 필터링assertThat(posts).filteredOn(p -> p.getStatus().equals("PUBLISHED")).hasSize(2);
Post post = postService.findById(1L);// usingRecursiveComparison: 재귀적으로 모든 필드 비교 (equals 구현 불필요)assertThat(post).usingRecursiveComparison().ignoringFields("createdAt","updatedAt")// 제외할 필드 지정.isEqualTo(expectedPost);// 특정 필드만 검증assertThat(post).hasFieldOrPropertyWithValue("title","Spring Boot 입문").hasFieldOrPropertyWithValue("status","PUBLISHED");
// 예외가 반드시 발생해야 통과assertThatThrownBy(()-> postService.findById(999L)).isInstanceOf(ResourceNotFoundException.class).hasMessage("Post not found: 999").hasMessageContaining("not found");// 예외 발생 + 원인(cause) 확인assertThatThrownBy(()-> service.create(command)).isInstanceOf(DuplicateResourceException.class).hasCauseInstanceOf(DataIntegrityViolationException.class);
// 예외가 발생하지 않아야 통과assertThatCode(()-> postService.create(validCommand)).doesNotThrowAnyException();// 예외가 발생해야 하지만, assertThatThrownBy보다 유연한 검증assertThatCode(()->invalidOperation()).isInstanceOf(IllegalArgumentException.class);
@DisplayName("PostService 테스트")classPostServiceTest{privatePostService postService;privateFakePostRepository fakePostRepository;@BeforeEachvoidsetUp(){ fakePostRepository =newFakePostRepository(); postService =newPostService(fakePostRepository);}@Test@DisplayName("제목과 내용으로 게시글을 생성하면 저장된 게시글을 반환한다")voidcreatePost_success(){// GivenCreatePostCommand command =newCreatePostCommand("제목","내용","PUBLISHED");// WhenPost post = postService.create(command);// ThenassertThat(post.getId()).isNotNull();assertThat(post.getTitle()).isEqualTo("제목");assertThat(post.getStatus()).isEqualTo("PUBLISHED");}@Test@DisplayName("존재하지 않는 게시글 조회 시 ResourceNotFoundException이 발생한다")voidfindById_notFound_throwsException(){// When & ThenassertThatThrownBy(()-> postService.findById(999L)).isInstanceOf(ResourceNotFoundException.class).hasMessageContaining("999");}}
// 일반 assertThat: 첫 번째 실패 시 멈춤// SoftAssertions: 모든 검증 실행 후 전체 실패 목록 출력@TestvoidcheckMultipleFields(){SoftAssertions soft =newSoftAssertions(); soft.assertThat(post.getTitle()).isEqualTo("제목"); soft.assertThat(post.getStatus()).isEqualTo("PUBLISHED"); soft.assertThat(post.getViewCount()).isGreaterThanOrEqualTo(0); soft.assertAll();// 실패한 검증 전부 출력}