-
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
주니어 개발자를 위한 단위테스트 샘플 코드 소개
자바&스프링 환경에서 단위 테스트 경험해보기 | (2021.06.15) 추가 의견 이 글을 작성한지 1년이란 시간이 지났습니다.. 제가 쓴글을 다시 읽어보니 좋은 글인지 확신이 없습니다. 별로 도움이 안될
brunch.co.kr
https://brunch.co.kr/@springboot/207
스프링부트 테스트
스프링 부트 Unit Test 및 Integration Test | 테스트코드를 작성하는 일은 정말 중요하다. 하지만, 필자에게 아직도 너무 어려운 일이 바로 테스트 코드를 작성하는 일이다. TDD 를 잘하는 개발자는 필
brunch.co.kr
https://brunch.co.kr/@springboot/292
Given-When-Then Pattern
테스트 코드 작성 표현 방법 (스프링 부트 환경에서) | 이번 글에서는, 테스트 코드 작성 시 자주 사용하는 Given-When-Then Pattern에 대해서 간략하게 소개하겠다. 별 내용 없는 글이므로, 아주 편한
brunch.co.kr
https://www.javacodegeeks.com/2021/03/testing-the-file-upload-api-in-spring-boot.html
Testing the File Upload API in Spring Boot - Java Code Geeks - 2021
Interested to learn about File Upload API? Check our article explaining how to Test the File Upload API in Spring Boot
www.javacodegeeks.com
'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