import org.junit.jupiter.api.Test;
public class JunitDefaultStructure {
@Test
public void test1() {
// 테스트 하고자 하는 대상에 대한 테스트 로직 작성
}
@Test
public void test2() {
// 테스트 하고자 하는 대상에 대한 테스트 로직 작성
}
@Test
public void test3() {
// 테스트 하고자 하는 대상에 대한 테스트 로직 작성
}
}
import static org.assertj.core.api.Assertions.*;
// entry point for all assertThat methods and utility methods (e.g. entry)
import static org.assertj.core.api.Assertions.*;
// basic assertions
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
// chaining string specific assertions
assertThat(frodo.getName()).startsWith("Fro")
.endsWith("do")
.isEqualToIgnoringCase("frodo");
// collection specific assertions (there are plenty more)
// in the examples below fellowshipOfTheRing is a List<TolkienCharacter>
assertThat(fellowshipOfTheRing).hasSize(9)
.contains(frodo, sam)
.doesNotContain(sauron);
// as() is used to describe the test and will be shown before the error message
assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
// exception assertion, standard style ...
assertThatThrownBy(() -> { throw new Exception("boom!"); }).hasMessage("boom!");
// ... or BDD style
Throwable thrown = catchThrowable(() -> { throw new Exception("boom!"); });
assertThat(thrown).hasMessageContaining("boom");
// using the 'extracting' feature to check fellowshipOfTheRing character's names
assertThat(fellowshipOfTheRing).extracting(TolkienCharacter::getName)
.doesNotContain("Sauron", "Elrond");
// extracting multiple values at once grouped in tuples
assertThat(fellowshipOfTheRing).extracting("name", "age", "race.name")
.contains(tuple("Boromir", 37, "Man"),
tuple("Sam", 38, "Hobbit"),
tuple("Legolas", 1000, "Elf"));
// filtering a collection before asserting
assertThat(fellowshipOfTheRing).filteredOn(character -> character.getName().contains("o"))
.containsOnly(aragorn, frodo, legolas, boromir);
// combining filtering and extraction (yes we can)
assertThat(fellowshipOfTheRing).filteredOn(character -> character.getName().contains("o"))
.containsOnly(aragorn, frodo, legolas, boromir)
.extracting(character -> character.getRace().getName())
.contains("Hobbit", "Elf", "Man");
@SpringBootTest
를 이용한 controller 테스트 클래스 기본 구조@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTestDefaultStructure {
@Autowired
private MockMvc mockMvc;
@Test
public void postMemberTest() {
// given
// when
// then
}
}
MockMvc
의 기능을 사용하기 위해 @AutoConfigureMockMvc
를 추가해야 한다.
MockMvc
는 서버를 실행시키지 않고 Spring 기반 애플리케이션을 테스트 할 수 있는 환경을 지원해주는 테스트 프레임워크이다.
@WebMvcTest
를 이용한 controller 테스트 클래스 기본 구조@ExtendWith(SpringExtension.class)
@WebMvcTest(Controller.class)
public class ControllerTestDefaultStructure {
@Autowired
private MockMvc mockMvc;
@Test
public void postMemberTest() {
// given
// when
// then
}
}
@WebMvcTest
는 MVC 부분 슬라이스 테스트로, 보통 컨트롤러 하나만 테스트하고 싶을 때 사용한다. @SpringBootTest
에는 다음과 같이 @ExtendWith(SpringExtension.class)
가 포함되어 있다.
@SpringBootTest + @AutoConfigureMockMvc
VS @WebMvcTest
@SpringBootTest
는 통합 테스트에 해당된다. 기본적으로 @SpringBootTest
어노테이션을 이용하면 스프링이 관리하는 모든 빈을 등록시켜 테스트하기 때문에 무겁다. 하지만 @WebMvcTest
는 웹과 관련된 빈들만 등록하므로 비교적 가볍다. 웹 레이어 관련 빈들만 등록되므로 Service는 등록되지 않는다.(즉, @Component
는 스캔 대상에서 제외) 따라서 @MockBean
어노테이션을 이용해 가짜 객체를 만들어줘야한다.데이터 엑세스 계층 테스트 시에는 테스트 종료 후, DB의 상태를 테스트 케이스 실행 이전으로 되돌려서 깨끗하게 만들어야한다.
@DataJpaTest
public class MemberRepositoryTest {
...
...
@Test
public void findByEmailTest() {
// given
Member member = new Member();
member.setEmail("hgd@gmail.com");
member.setName("홍길동");
member.setPhone("010-1111-2222");
// when
memberRepository.save(member);
Optional<Member> findMember = memberRepository.findByEmail(member.getEmail());
// then
assertTrue(findMember.isPresent());
assertTrue(findMember.get().getEmail().equals(member.getEmail()));
}
}
@DataJpaTest
어노테이션을 이용하여 하나의 테스트 케이스 실행이 종료되는 시점에 데이터베이스에 저장된 데이터는 rollback처리한다.
rollback이 되는 이유는 @DataJpaTest
어노테이션 내부에 @Transactional
어노테이션이 존재하기 때문이다.