-
TDD (Test Driven Development) : 단위 테스트 작성하기Spring 2021. 10. 26. 17:18
개발단계에서의 오류와 자체 버그 검출 능력을 향상시키기 위해서
TDD(테스트 주도 개발)의 개발이 사용되고 있다.
TDD를 통해 개발을 진행한다면 코드 재사용과 관리가 용이해지므로 테스트 주도 개발을 하는 습관을 들이도록 하자.
(나는 완전 초보이므로 ㅠㅠ 이제 단위테스트의 부분부분을 배워가고 있다)
F.I.R.S.T 원칙
단위 테스트 코드를 작성할 때 주의해야 하는 원칙은 5가지 이다.
- F : Fast -> 테스트 코드는 빨리 진행이 되어야 한다.
- I : Independent -> 독립적으로 실행이 가능해야 한다.
- R : Repeatable -> 반복이 가능해야 한다.
- S : Self Validating -> 테스트 코드만 실행해도 성공여부를 확인할 수 있어야 한다.
- T : Timely -> 바로 사용이 가능해야 한다.
Given, When, Then
테스트 코드 작성시 가장 기본적으로 지켰던 규칙은 given, when, then 의 패턴이다. 준비 -> 실행 -> 검증의 단계로 이루어진다.
- Given : 테스트 코드에 필요한 값, 또는 Mock 객체 정의
- When : 테스트 하고자 하는 코드 실행
- Then : 결과 값이 원하고자 하는대로 잘 실행되었는지 검증
Dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
스프링 부트 테스트 진행을 위하여 위의 3가지 dependency를 pom.xml에 추가해주자.
spring-boot-test 로 인해서 JUnit4, Spring Test & Spring Boot Test, AssertJ, Hamcrest, Mockito, JSONassert, JsonPath 가 자동 설정된다.
RepositoryTest
@Rollback(false) @SpringBootTest @ExtendWith(SpringExtension.class) @Transactional public class UserRepositoryTests { @Autowired UserRepository userRepository; @Autowired PasswordEncoder passwordEncoder; @Test public void createUser(){ //given String firstName = "testFirstName"; String lastName = "testLastName"; String email = "test@example.com"; String password = "123456"; Role role = Role.USER; Level level = Level.Starter; User user = new User(); user.setFirstname(firstName); user.setLastname(lastName); user.setEmail(email); user.setPassword(passwordEncoder.encode(password)); user.setRole(role); user.setLevel(level); //when User user1 = userRepository.save(user); //then assertThat(user1.getId()).isNotNull(); assertThat(user1.getFirstname()).isEqualTo(firstName); assertThat(user1.getLastname()).isEqualTo(lastName); assertThat(user1.getEmail()).isEqualTo(email); assertThat(passwordEncoder.matches(password, user1.getPassword())); assertThat(user1.getRole()).isEqualTo(role); assertThat(user1.getLevel()).isEqualTo(level); } }
Repository테스트를 진행하는데, Repostiory는 데이터 변화상태를 보기 위해서 Rollback(false)로 진행해주었다. @Transactional을 통해서 데이터 변경이 가능하도록 설정하여 진행하였다.
ServiceTest
@RunWith(SpringRunner.class) @SpringBootTest @Transactional public class UserServiceTests { @Autowired UserService userService; @Autowired UserRepository userRepository; @Autowired PasswordEncoder passwordEncoder; @Test public void singUp() throws IOException { //given String firstname = "test"; String lastname = "register"; String email = "test@example.com"; String password = "123456"; String phoneNumber = "01000000000"; String description = "This is test."; UserRegisterDTO userRegisterDTO = new UserRegisterDTO(firstname, lastname,email,password,phoneNumber,description,false); MultipartFile multipartFile = new MockMultipartFile("uploaded-file", "sampleFile.txt", "text/plain", "This is the file content".getBytes()); //when UserDTO userDTO = userService.saveUser(userRegisterDTO,multipartFile); //then assertNotNull(userDTO.getId()); assertEquals(firstname, userDTO.getFirstname()); assertEquals(lastname,userDTO.getLastname()); assertEquals(email,userDTO.getEmail()); assertTrue(passwordEncoder.matches(password, userRepository.findById(userDTO.getId()).get().getPassword())); assertEquals(phoneNumber,userDTO.getPhoneNumber()); assertEquals(description,userDTO.getDescription()); assertEquals("/profileUploads/" + userDTO.getId() + "/" + "sampleFile.txt",userDTO.getImageUrl()); }
ServiceTest는 테스트 종료후 rollback이 가능하도록 따로 Rollback 설정을 해주지 않았고 (springBootTest어노테이션 사용시에 테스트 종료후 rollback이 된다) @Transactional어노테이션도 사용하였다. 여기서 사용된 테스트에서는 Mock파일 을 생성해서 가짜 파일이 제대로 저장되는지도 확인해 주었다.
테스트에서의 @Transactional
@Transactional은 데이터 읽기에서는 필요하지 않으므로, 기본을 @Transactional(readonly)로 설정해주고 데이터 변경이 필요한 부분에만 @Transactional을 설정해주는 것이 좋다.
(참고가 많이 된 사이트 & 참고해서 배워야 할 사이트 😭)
https://brunch.co.kr/@springboot/418
https://brunch.co.kr/@springboot/207
https://brunch.co.kr/@springboot/292
https://www.javacodegeeks.com/2021/03/testing-the-file-upload-api-in-spring-boot.html
'Spring' 카테고리의 다른 글
SMTP 서버를 통한 이메일 보내기 (0) 2021.10.26 OAuth2 사용해서 react와 함께 소셜로그인 기능 만들기 (4) 2021.10.26 JPA delete 쿼리가 실행되지 않을 때 (0) 2021.10.26 Controller와 RestController ( + ResponseEntity) (0) 2021.10.26 DTO를 통해 mapping된 엔티티 데이터 묶어서 보내기 ( + 순환참조 방지 DTO) (2) 2021.10.26