본문 바로가기
개발 일지/Day by day

2024-02-22 TIL

by 쁘띠뀨띠 2024. 2. 22.

Mockito

@Mock
private UserRepository userRepository;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
JwtUtil jwtUtil;
private HttpServletResponse res;
@InjectMocks
private UserService userService;
@Captor
private ArgumentCaptor<User> userCaptor;

 

@Mock

테스트 대상 클래스에서 사용되는 외부 의존성을 대체, 특정 객체에 의존하고 있을때, 주입하는 대신에 @Mock을 사용해 객체를 생성할 수 있다.

실제 객체와 동일한 인터페이스를 가지고 있지만, 동작은 직접 정의할 수 있다. (테스트의 격리성 유지)

실제 동작이 구현되어 있지 않으므로 Mock객체의 동작을 정의해야한다.

when - then / given - willReturn

when(mockObject.methodCall(argument)).thenReturn(value);

given(mockObject.methodCall(argument)).willReturn(value);

- mockObject : 목의 객체

- methodCall : 객체에서 호출될 메서드

- argument : 메서드의 매개변수

- value : 반환값

 

@InjectMocks

필드 클래스에대한 의존성을 주입한다.

생성자를 통한 주입과는 다르게 생성자가 호출되지 않는다.

따라서 생성자에서 초기화되는 의존성이 있는 경우, 초기화 할 수 없으니 주의!

 

@Captor

Mockito에서 제공하는 애노테이셔느로, 메서드 호출 시 전달된 인자를 캡쳐해 검증할 수 있도록한다.

주로 verify 메서드와 함께 사용된다.

 

- 서비스 로직

@Transactional
public void signup(SignupRequestDto requestDto) {
    String username = requestDto.getUsername();
    String password = passwordEncoder.encode(requestDto.getPassword());
    UserRoleEnum role = requestDto.getRole();
    userRepository.save(new User(username, password,role));
}

 

- 테스트 코드

@Captor
private ArgumentCaptor<User> user;
@Test
void signup() {
    // give
    SignupRequestDto signupRequestDto = new SignupRequestDto();
    signupRequestDto.setUsername("rjsld");
    signupRequestDto.setPassword("1234");
    signupRequestDto.setRole(UserRoleEnum.USER);

    when(passwordEncoder.encode("1234")).thenReturn("encodedPassword");

    // when
    userService.signup(signupRequestDto);

    // then
    verify(userRepository).save(userCaptor.capture());
    User testUser = userCaptor.getValue();
    assertEquals("rjsld 와", testUser.getUsername()+"는 같습니다.");

}

 

 

userRepository.save() 메서드가 호출될때 전달된 User 객체를 @Captor의 userCaptor에 저장한다.

verify ~ 코드를 통해 한 번 호출되었는지 검증하면서 메서드 호출 시 전달된 User객체를 검증할 수 있다.

getValue()를 통해 캡처한 값을 가져올 수 있다.

 

@Test
void updateProfile() {
    // give
    Long id = 1L;
    UserRequestDto userRequestDto = new UserRequestDto();
    userRequestDto.setPassword("1234");
    userRequestDto.setIntro("반갑습니다.");

    String encodePassword = "4321";
    User user = new User(id,"rjsld",encodePassword,"안녕하세요");

    given(userRepository.findById(id)).willReturn(Optional.of(user));
    given(passwordEncoder.matches("1234", encodePassword)).willReturn(true);
    given(passwordEncoder.encode("1234")).willReturn(encodePassword);

   // when
   userService.updateProfile(id,userRequestDto);

   assertEquals("반갑습니다 = ", user.getIntro());
}

 


- 서비스 로직

    //프로필 수정
    @Transactional
    public UserResponseDto updateProfile(Long id, UserRequestDto dto) {
        User user = checkPWAndGet(id, dto.getPassword());

        user.setPassword(passwordEncoder.encode(dto.getPassword()));
        user.setIntro(dto.getIntro());

        return new UserResponseDto(user);

    }

//    //프로필 비밀번호 체크
    private User checkPWAndGet(Long id, String password) {
        User user = getUser(id);
        // 비밀번호 체크
        if (!passwordEncoder.matches(password,user.getPassword())) {
            throw new IllegalArgumentException("잘못된 비밀번호입니다.");
        }
//        if (user.getPassword() != null && !Objects.equals(user.getPassword(),password)) {
//            throw new IllegalArgumentException();
//        }
        return user;
    }

 

- 테스트 코드

    @Test
    void updateProfile() {
        // give
        Long id = 1L;
        UserRequestDto userRequestDto = new UserRequestDto();
        userRequestDto.setPassword("1234");
        userRequestDto.setIntro("반갑습니다.");

        String encodePassword = "4321";
        User user = new User(id,"rjsld",encodePassword,"안녕하세요");

        given(userRepository.findById(id)).willReturn(Optional.of(user));
        given(passwordEncoder.matches("1234", encodePassword)).willReturn(true);
//        given(passwordEncoder.encode("1234")).willReturn(encodePassword);

       // when
       userService.updateProfile(id,userRequestDto);

       assertEquals("반갑습니다 = ", user.getIntro());
    }

 

암호화된 비밀번호를 matches() 메서드를 사용해 두 값을 인자로 받았을때 항상 true가 나오도록 설정한다.

 

 

'개발 일지 > Day by day' 카테고리의 다른 글

2024-02-06 TIL  (0) 2024.02.06
2024-01-31 TIL  (0) 2024.01.31
2024-01-26 TIL  (1) 2024.01.26
2024-01-23 TIL  (1) 2024.01.24
2024-01-18 TIL  (0) 2024.01.18