새 프로젝트 돌입 전 이론 수업
유닛 테스트에 대해 이론 수업이 진행됐다.
✅ 단위 테스트 & 통합 테스트
- 단위 테스트 : 메서드 하나하나 개별적으로 테스트함
- 통합 테스트 : 어플리케이션이 정상적으로 동작하는지 테스트함. (controller, repository, service ... 전부 실행. 즉 우리가 포스트맨으로 했던 것들!)
✅ F.I.R.S.T 원칙
- Fast : 단위 테스트는 빨라야 한다.
- Independent : 단위 테스트는 각각의 테스트가 연관되지 않고, 고립되어야 한다. 즉 독립적 이어야 한다.
- Repeatable : 단위테스트는 반복 가능해야한다. 반복적으로 테스트를 시행해도, 결과는 같아야 한다.
- Self-validating : 자체적으로 테스트 결과가 도출되야한다. (개발자가 print 찍어서 비교하는게 아니고 자동으로 수행되며 성공/실패 의 결과가 나오는 것)
- Timely : 단위 테스트는 실제 코드보다 먼저 구현해야한다. (TDD일 경우에만 해당)
💡 TDD?
테스트 주도 개발(Test-driven development TDD) :
매우 짧은 개발 사이클을 반복하는 소프트웨어 개발 프로세스 중 하나이다.
실행 주기 :
<Red> 단계 : 실패하는 테스트 코드를 먼저 작성한다.
<Green> 단계 : 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
<Yellow> 단계 : 중복 코드 제거, 일어 반환 등의 리팩토링을 수행한다.
이 기법을 개발했거나 '재발견' 한 것으로 인정되는 Kent Beck은 2003년에 TDD가 단순한 설계를 장려하고 자신감을 불어넣어준다고 말하였다.
더 자세히 알고 싶으면 실행 주기 사진을 클릭하면 된다.
✅ Given-When-Then 패턴
- Given : 테스트에 필요한 변수를 정의하거나 Mock 객체를 통해 특정 상황에 대한 행동을 정의다.
- When : 실제 테스트를 하는 메소드가 호출되며 테스트를 통한 결과값을 가져온다.
- Then : When 단계에서 나온 결과값을 검증하는 작업을 수행한다.
✅JUnit + Mockito
- JUnit : Java 에서 사용되는 대표적인 테스트 프레임워크. 자바 개발자 93% 가 사용한다는 통계가 있다.
- Mockito : Mock 객체를 쉽게 만들고, 관리하고, 검증할 수 있는 방법을 제공하는 프레임워크이다. Mock 객체는 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 행동을 관리하는 객체이다.
💡 Mockito에서 Mock(가짜) 객체의 의존성 주입을 위해서는 크게 3가지 어노테이션이 사용된다.
@Mock : Mock 객체를 만들어 반환해주는 어노테이션
@Spy : Stub하지 않은 메소드들은 원본 메소드 그대로 사용하는 어노테이션
@InjectMocks : @Mock 또는 @Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션
예를 들어 UserController에 대한 단위 테스트를 작성하고자 할 때, UserService를 사용하고 있다면 @Mock 어노테이션을 통해 가짜 UserService를 만들고, @InjectMocks를 통해 UserController에 이를 주입시킬 수 있다.
✅ 라이브 코딩 보면서 내 코드도 같이 따라 짜보기!
1. 테스트 코딩할 파일을 연다.
2. 클래스 명 우클릭해서 Generate > Test를 누른다음 테스트 할 메서드 선택
3. @ExtendWith(MockitoExtension.class) 어노테이션을 걸어준다
4. @Mock, @InjectMocks 어노테이션을 걸어준다.
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void signUp() {
}
@Test
void login() {
}
}
5. @Spy 어노테이션으로 실제 우리가 가져올 값들을 지정해준다.
@Spy
private JwtUtil jwtUtil;
@Spy
private PasswordEncoder passwordEncoder;
6. @Builder 어노테이션을 쓸 것이기 때문에 내가 얻고싶은 Dto에 가서 Builder 어노테이션 생성해준다
@Builder
public SignUpRequestDto(String username, String nickName, String password, String image, boolean admin) {
this.username = username;
this.nickName = nickName;
this.password = password;
this.image = image;
this.admin = admin;
}
7. test에서 원하는 빌드를 생성한다.
@Test
@DisplayName("회원가입")
void signUp() {
// given
SignUpRequestDto requestDto = SignUpRequestDto.builder()
.admin(false)
.username("dorong")
.password("190226dr")
.image("naver.com")
.nickName("DorongZZang")
.build();
8. 회원 가입때 우리가 만들어놓은 가짜 빌드를 불러오기 위해 아래와 같은 코드를 짜준다.
when(userRepository.findByUsername(any(String.class)))
.thenReturn(Optional.empty());
근ㄷㅔ 왜 계속 에러나지,,,?티부래...
후발대 스터디
Ctrl + D : 커서가 있는 줄 전체 복사해서 아랫줄에 복붙해줌!
Alt + Ins : 생성자 만들어준다.
제너릭스에 대해 제대로 배웠다!!! 어렴풋하게 개념만 사알짝 잡고 있었는데 이번에 상속받는 개념이랑 기타 등등 여러 방식으로 쓸 수 있는 법, 클래스 만들어서 메서드 가져올 때 어떻게 쓰는지 등등을 알게 되었다!
특히 문자열, 숫자형 상관 없이 쓸 수 있는 게 너무 신기했음!