content: package com.codesoom.demo.application;
  
  import com.codesoom.demo.domain.Role;
  import com.codesoom.demo.domain.RoleRepository;
  import com.codesoom.demo.domain.User;
  import com.codesoom.demo.domain.UserRepository;
  import com.codesoom.demo.errors.InvalidTokenException;
  import com.codesoom.demo.errors.LoginFailException;
  import com.codesoom.demo.utils.JwtUtil;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  
  import java.util.Arrays;
  import java.util.Optional;
  import java.util.stream.Collectors;
  
  import static org.assertj.core.api.Assertions.assertThat;
  import static org.assertj.core.api.Assertions.assertThatThrownBy;
  import static org.mockito.BDDMockito.given;
  import static org.mockito.Mockito.mock;
  import static org.mockito.Mockito.verify;
  
  class AuthenticationServiceTest {
      private static final String SECRET = "12345678901234567890123456789012";
  
      private static final String VALID_TOKEN = "eyJhbGciOiJIUzI1NiJ9." +
              "eyJ1c2VySWQiOjF9.ZZ3CUl0jxeLGvQ1Js5nG2Ty5qGTlqai5ubDMXZOdaDk";
      private static final String INVALID_TOKEN = "eyJhbGciOiJIUzI1NiJ9." +
              "eyJ1c2VySWQiOjF9.ZZ3CUl0jxeLGvQ1Js5nG2Ty5qGTlqai5ubDMXZOdaD0";
  
      private AuthenticationService authenticationService;
  
      private UserRepository userRepository = mock(UserRepository.class);
      private RoleRepository roleRepository = mock(RoleRepository.class);
  
      @BeforeEach
      void setUp() {
          JwtUtil jwtUtil = new JwtUtil(SECRET);
  
          authenticationService = new AuthenticationService(
                  userRepository, roleRepository, jwtUtil);
  
          User user = User.builder()
                  .password("test")
                  .build();
  
          given(userRepository.findByEmail("tester@example.com"))
                  .willReturn(Optional.of(user));
  
          given(roleRepository.findAllByUserId(1L))
                  .willReturn(Arrays.asList(new Role("USER")));
          given(roleRepository.findAllByUserId(1004L))
                  .willReturn(Arrays.asList(new Role("USER"), new Role("ADMIN")));
      }
  
      @Test
      void loginWithRightEmailAndPassword() {
          String accessToken = authenticationService.login(
                  "tester@example.com", "test");
  
          assertThat(accessToken).isEqualTo(VALID_TOKEN);
  
          verify(userRepository).findByEmail("tester@example.com");
      }
  
      @Test
      void loginWithWrongEmail() {
          assertThatThrownBy(
                  () -> authenticationService.login("badguy@example.com", "test")
          ).isInstanceOf(LoginFailException.class);
  
          verify(userRepository).findByEmail("badguy@example.com");
      }
  
      @Test
      void loginWithWrongPassword() {
          assertThatThrownBy(
                  () -> authenticationService.login("tester@example.com", "xxx")
          ).isInstanceOf(LoginFailException.class);
  
          verify(userRepository).findByEmail("tester@example.com");
      }
  
      @Test
      void parseTokenWithValidToken() {
          Long userId = authenticationService.parseToken(VALID_TOKEN);
  
          assertThat(userId).isEqualTo(1L);
      }
  
      @Test
      void parseTokenWithInvalidToken() {
          assertThatThrownBy(
                  () -> authenticationService.parseToken(INVALID_TOKEN)
          ).isInstanceOf(InvalidTokenException.class);
      }
  
      @Test
      void roles() {
          assertThat(
                  authenticationService.roles(1L).stream()
                          .map(Role::getName)
                          .collect(Collectors.toList())
          ).isEqualTo(Arrays.asList("USER"));
  
          assertThat(
                  authenticationService.roles(1004L).stream()
                          .map(Role::getName)
                          .collect(Collectors.toList())
          ).isEqualTo(Arrays.asList("USER", "ADMIN"));
      }
  }
  