Post

대용량 트래픽 경험해보기(2/14) - 회원/인증 테스트 코드 작성(TDD, Mockito) & API 자동화 문서(Swagger)

개발 전 시행해야할 부분으로 회원 및 토큰 발급에 대해서 테스트에 필요한 작업들을 TDD 기반으로 진행했으며, 동작에 대해서는 Mockito 프레임워크를 통해 테스트를 진행했다.

기능 구분테스트 구분세부 테스트 구분
1. 회원가입 및 조회1.1 회원 추가 - 이메일 중복
- 회원 가입 실패
- 회원 가입 성공
1.2 회원 조회 - 회원 조회 실패
- 회원 조회 성공
1. 회원가입 및 조회1.1 회원 추가 - 닉네임 중복
- 닉네임 변경 실패
- 닉네임 변경 성공
2. 토큰 발급2.1 토큰 발급 및 재발급 테스트 - 토큰 정상 발급 테스트
- 토큰 만료 및 유효성 테스트
- 토큰 재발급 테스트

슬라이스 테스트 - 회원

회원 Repository 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@DisplayName("회원 Repository 테스트")
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserRepositoryMockTests {

  @Mock
  MemberRepository memberRepository;

  @Test
  @Order(1)
  @DisplayName("사용자 회원 이메일 중복 테스트")
  public void 사용자_회원_이메일_중복_테스트(){

    //given
    String duplicatedEmail = "test1@gmail.com";
    when(memberRepository.getDuplicatedEmailId(any(String.class))).thenReturn(2L);

    //when
    Long result = memberRepository.getDuplicatedEmailId(duplicatedEmail);

    //then
    assertTrue(result > 0);
  }

  @Test
  @Order(2)
  @DisplayName("사용자 회원가입 테스트")
  public void 사용자_회원가입_테스트(){

    //given
    Member member = new Member(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.of("USER").getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    Member savedMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.of("USER").getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    when(memberRepository.save(any(Member.class))).thenReturn(savedMember);

    //when
    Member result = memberRepository.save(member);

    //then
    assertEquals(1L, result.getMemberId());
    assertEquals("test1@gmail.com", result.getMemberEmail());
    assertEquals("테스트이름1", result.getMemberName());
    assertEquals("테스트닉네임1", result.getNickName());
    assertEquals("010-0000-0000", result.getPhoneNumber());
    assertEquals(32, result.getAge());
    assertEquals(LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), result.getBirthday());
    assertEquals('M', result.getGender());
    assertEquals(0, result.getDomancy());
    assertEquals(MemberRoleEnum.USER.getRole(), result.getMemberRole());
    assertEquals(AccountTypeEnum.GOOGLE.getType(), result.getAccountType());
  }

  @Test
  @Order(3)
  @DisplayName("사용자 회원 닉네임 중복 테스트")
  public void 사용자_회원_닉네임_중복_테스트(){
    //given
    when(memberRepository.getDuplicatedNickNameId(any(Long.class), any(String.class))).thenReturn(2L);

    //when
    Long result = memberRepository.getDuplicatedNickNameId(1L, "테스트닉네임변경1");

    //then
    assertTrue(result > 0);
  }

  @Test
  @Order(4)
  @DisplayName("사용자 회원 닉네임 수정 테스트")
  public void 사용자_회원_닉네임_수정_테스트(){

    //given
    when(memberRepository.modifyNickName(any(Long.class), any(String.class), any(Long.class))).thenReturn(1L);

    //when
    long result = memberRepository.modifyNickName(1L, "테스트닉네임변경1", 1L);

    //then
    assertTrue(result > 0);
  }

  @Test
  @Order(5)
  @DisplayName("사용자 회원 조회 테스트")
  public void 사용자_회원_조회_테스트(){
    //given
    Long memberId = 1L;

    Member findMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.of("USER").getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );
    when(memberRepository.findById(any(Long.class))).thenReturn(Optional.of(findMember));

    //when
    Member result = memberRepository.findById(memberId).get();

    //then
    assertEquals(1L, result.getMemberId());
    assertEquals("test1@gmail.com", result.getMemberEmail());
    assertEquals("테스트이름1", result.getMemberName());
    assertEquals("테스트닉네임1", result.getNickName());
    assertEquals("010-0000-0000", result.getPhoneNumber());
    assertEquals(32, result.getAge());
    assertEquals(LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), result.getBirthday());
    assertEquals('M', result.getGender());
    assertEquals(0, result.getDomancy());
    assertEquals(MemberRoleEnum.USER.getRole(), result.getMemberRole());
    assertEquals(AccountTypeEnum.GOOGLE.getType(), result.getAccountType());
  }
}

Member Repository Test Result

회원 Service 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
@DisplayName("회원 Service 테스트")
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserServiceMockTests {

  @Mock
  MemberRepository memberRepository;

  @InjectMocks
  MemberService memberService;

  @Test
  @Order(1)
  @DisplayName("회원서비스 회원가입 테스트")
  public void 회원서비스_회원가입_테스트(){
    //given
    MemberDto memberDto = new MemberDto(
        1L,"test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    Member savedMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );
    savedMember.setMemberId(1L);

    when(memberRepository.getDuplicatedEmailId(any(String.class))).thenReturn(0L);
    when(memberRepository.save(any(Member.class))).thenReturn(savedMember);

    //when
    Long result = memberService.createMember(memberDto);

    //then
    assertEquals(1L, result);
    verify(memberRepository, times(1)).getDuplicatedEmailId(any(String.class));
    verify(memberRepository, times(1)).save(any(Member.class));
  }

  @Test
  @Order(2)
  @DisplayName("회원서비스 회원가입 이메일중복 실패 테스트")
  public void 회원서비스_회원가입_이메일중복_실패_테스트(){
    //given
    MemberDto memberDto = new MemberDto(
        1L,"test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    Member savedMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );
    savedMember.setMemberId(1L);

    when(memberRepository.getDuplicatedEmailId(any(String.class))).thenThrow(CommonException.class);

    //when
    assertThrows(CommonException.class, () -> {
        Long result = memberService.createMember(memberDto);
      }
    );

    //then
    verify(memberRepository, times(1)).getDuplicatedEmailId(any(String.class));
  }

  @Test
  @Order(3)
  @DisplayName("회원서비스 회원 닉네임 변경 중복오류 테스트")
  public void 회원서비스_회원_닉네임_변경_중복오류_테스트(){
    //given
    Long memberId = 1L;
    String nickName = "테스트닉네임변경1";

    Member savedMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );
    savedMember.setMemberId(1L);

    when(memberRepository.getDuplicatedNickNameId(any(Long.class), any(String.class))).thenThrow(CommonException.class);

    //when
    assertThrows(CommonException.class, () -> {
        memberService.modifyNickName(memberId, nickName);
      }
    );

    //then
    verify(memberRepository, times(1)).getDuplicatedNickNameId(any(Long.class), any(String.class));
  }

  @Test
  @Order(4)
  @DisplayName("회원서비스 회원 닉네임 변경 테스트")
  public void 회원서비스_회원_닉네임_변경_테스트(){
    //given
    Long memberId = 1L;
    String nickName = "테스트닉네임변경1";

    Member savedMember = new Member(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );
    savedMember.setMemberId(1L);

    when(memberRepository.getDuplicatedNickNameId(any(Long.class), any(String.class))).thenReturn(0L);
    when(memberRepository.modifyNickName(any(Long.class), any(String.class))).thenReturn(1L);

    //when
    memberService.modifyNickName(memberId, nickName);

    //then
    verify(memberRepository, times(1)).getDuplicatedNickNameId(any(Long.class), any(String.class));
    verify(memberRepository, times(1)).modifyNickName(any(Long.class), any(String.class));
  }

}

Member Service Test Result

회원 Controller 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
@DisplayName("회원 Controller 테스트")
@SpringBootTest
@ActiveProfiles("local")
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserControllerMockTests {

  @Autowired
  MockMvc mockMvc;

  @MockBean
  MemberService memberService;

  @Autowired
  ObjectMapper objectMapper;

  @Test
  @Order(1)
  @DisplayName("회원컨트롤러 회원가입 이메일중복 실패 테스트")
  public void 회원컨트롤러_회원가입_이메일중복_실패_테스트() throws Exception {
    //given
    MemberDto memberDto = new MemberDto(
        null,"test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    CommonException commonException = new CommonException(ResponseCode.MEMBER_EXIST);
    when(memberService.createMember(any(MemberDto.class))).thenThrow(commonException);

    //when
    ResultActions actions = mockMvc.perform(
        post("/api/member")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(memberDto))
    );

    //then
    actions
        .andExpect(status().isConflict());
  }

  @Test
  @Order(2)
  @DisplayName("회원컨트롤러 회원가입 실패 테스트")
  public void 회원컨트롤러_회원가입_실패_테스트() throws Exception {
    //given
    MemberDto memberDto = new MemberDto(
        null,"test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    when(memberService.createMember(any(MemberDto.class))).thenReturn(0L);

    //when
    ResultActions actions = mockMvc.perform(
        post("/api/member")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(memberDto))
    );

    //then
    actions
        .andExpect(status().isInternalServerError());
  }

  @Test
  @Order(3)
  @DisplayName("회원컨트롤러 회원가입 성공 테스트")
  public void 회원컨트롤러_회원가입_성공_테스트() throws Exception {
    //given
    MemberDto memberDto = new MemberDto(
        null,"test1@gmail.com", "테스트이름1", null, "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        MemberRoleEnum.USER.getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    when(memberService.createMember(any(MemberDto.class))).thenReturn(1L);

    //when
    ResultActions actions = mockMvc.perform(
        post("/api/member")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(memberDto))
    );

    //then
    actions
        .andExpect(status().isCreated());
  }

  @Test
  @Order(4)
  @DisplayName("회원컨트롤러 닉네임중복 변경 실패 테스트")
  public void 회원컨트롤러_닉네임중복_변경_실패_테스트() throws Exception {
    //given
    Long memberId = 1L;
    String nickName = "테스트닉네임1";
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";

    CommonException commonException = new CommonException(ResponseCode.MEMBER_NICKNAME_DUPLICATED);
    when(memberService.modifyNickName(any(Long.class), any(String.class), any(String.class))).thenThrow(commonException);

    //when
    ResultActions resultActions = mockMvc.perform(
        patch("/api/member/nickname/"+memberId)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", accessToken)
            .contentType(MediaType.APPLICATION_JSON)
            .content(nickName)
    );

    //then
    resultActions
        .andExpect(status().isConflict());
  }

  @Test
  @Order(5)
  @DisplayName("회원컨트롤러 닉네임 변경 실패 테스트")
  public void 회원컨트롤러_닉네임_변경_실패_테스트() throws Exception {
    //given
    Long memberId = 1L;
    String nickName = "테스트닉네임1";
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";

    when(memberService.modifyNickName(any(Long.class), any(String.class), any(String.class))).thenReturn(0L);

    //when
    ResultActions resultActions = mockMvc.perform(
        patch("/api/member/nickname/"+memberId)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", accessToken)
            .contentType(MediaType.APPLICATION_JSON)
            .content(nickName)
    );

    //then
    resultActions
        .andExpect(status().isInternalServerError());
  }

  @Test
  @Order(6)
  @DisplayName("회원컨트롤러 닉네임 변경 성공 테스트")
  public void 회원컨트롤러_닉네임_변경_성공_테스트() throws Exception {
    //given
    Long memberId = 1L;
    String nickName = "테스트닉네임1";
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";
    when(memberService.modifyNickName(any(Long.class), any(String.class), any(String.class))).thenReturn(1L);

    //when
    ResultActions resultActions = mockMvc.perform(
        patch("/api/member/nickname/"+memberId)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", accessToken)
            .contentType(MediaType.APPLICATION_JSON)
            .content(nickName)
    );

    //then
    resultActions
        .andExpect(status().isNoContent());
  }

  @Test
  @Order(7)
  @DisplayName("회원컨트롤러 NULL 회원 조회 테스트")
  public void 회원컨트롤러_NULL_회원_조회_테스트() throws Exception {
    //given
    Long memberId = 1L;
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";

    CommonException commonException = new CommonException(ResponseCode.MEMBER_NOT_FOUND);
    when(memberService.findMember(any(Long.class))).thenThrow(commonException);

    //when
    ResultActions resultActions = mockMvc.perform(
        get("/api/member/"+memberId)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", accessToken)
            .contentType(MediaType.APPLICATION_JSON)
    );

    //then
    resultActions
        .andExpect(status().isNotFound());
  }

  @Test
  @Order(8)
  @DisplayName("회원컨트롤러 회원 조회 테스트")
  public void 회원컨트롤러_회원_조회_테스트() throws Exception {
    //given
    Long memberId = 1L;
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";

    MemberResponseDto responseDto = new MemberResponseDto(
        1L, "test1@gmail.com", "테스트이름1", "테스트닉네임1", "010-0000-0000",
        32, LocalDate.parse("1991-08-09", DateTimeFormatter.ISO_DATE), 'M',
        0, MemberRoleEnum.of("USER").getRole(), AccountTypeEnum.of("GOOGLE").getType()
    );

    when(memberService.findMember(any(Long.class))).thenReturn(responseDto);

    //when
    ResultActions resultActions = mockMvc.perform(
        get("/api/member/"+memberId)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", accessToken)
            .contentType(MediaType.APPLICATION_JSON)
    );

    //then
    resultActions
        .andExpect(status().isFound());
  }
}

Member Controller Test Result

슬라이스 테스트 - 토큰

토큰 발급 Provider 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
@DisplayName("토큰 인증 Provider 테스트")
@SpringBootTest
@ActiveProfiles("local")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JwtAuthenticationTests {

  @Autowired
  private JwtTokenProvider jwtTokenProvider;

  @Test
  @Order(1)
  @DisplayName("JWT 토큰 발급 테스트")
  public void JWT_토큰_발급_테스트(){
    //given
    String memberEmail = "test1@gmail.com";
    long testTime = new Date().getTime();

    //when
    TokenResponseDto result = jwtTokenProvider.createToken(memberEmail, MemberRoleEnum.USER.getRole());

    //then
    assertTrue(result.getAccessToken() != null && result.getAccessToken().length() > 0);
    assertTrue(result.getAccessTokenExpiresIn() >= testTime);
    assertTrue(result.getRefreshToken() != null && result.getRefreshToken().length() > 0);
    assertTrue(result.getRefreshTokenExpiresIn() >= testTime);
  }

  @Test
  @Order(2)
  @DisplayName("JWT 토큰 Claims 데이터 테스트")
  public void JWT_토큰_Claims_데이터_테스트(){
    //given
    String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjM4MTksIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2NjI1NjE5fQ.-Fy5QrC4ZCbU-swm0kVJGCLIugYwEdXy2-zy0KEtuNInVQRDx7IsA0WGBZMC0W2eYJkt95jMoQXQdI6bik-F9w";

    //when
    Claims claims = jwtTokenProvider.getClaims(accessToken);

    //then
    assertEquals("test1@gmail.com", claims.getSubject());
    assertEquals(MemberRoleEnum.USER.getRole(), claims.get(JwtHeader.AUTHORITY_TYPE_HEADER.getValue(), String.class));
  }

  @Test
  @Order(3)
  @DisplayName("JWT 토큰 이메일 추출 테스트")
  public void JWT_토큰_이메일_추출_테스트(){
    //given
    String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjM4MTksIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2NjI1NjE5fQ.-Fy5QrC4ZCbU-swm0kVJGCLIugYwEdXy2-zy0KEtuNInVQRDx7IsA0WGBZMC0W2eYJkt95jMoQXQdI6bik-F9w";

    //when
    String memberEmail = jwtTokenProvider.getSubject(accessToken);

    //then
    assertEquals("test1@gmail.com", memberEmail);
  }

  @Test
  @Order(4)
  @DisplayName("JWT 정상 토큰 유효성 테스트")
  public void JWT_정상_토큰_유효성_테스트(){
    //given
    String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY3OTI4MDUsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2Nzk0NjA1fQ.c3kJ_n9E6MnS9vhwQ500r0s7lGozx1egeDG5FoAHAkhH2-zivpqH0JpBPonHfi_HcNYMLlPS8dc3Q23rfuMCPA";

    //when
    boolean tokenValid = jwtTokenProvider.validateToken(accessToken);

    //then
    assertTrue(tokenValid);
  }

  @Test
  @Order(5)
  @DisplayName("JWT 만료 토큰 유효성 테스트")
  public void JWT_만료_토큰_유효성_테스트(){
    //given
    String expiredAccessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjI1NzgsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2NjIyNTgwfQ.2zRSxfw79-oR4I2iwiYvgoPEHP0mGK6DS0Fh3YLC3YnHkqDR5Pxdz5aSfOvbolhPFzE-UwrI70aWa0Tu6--Mbg";

    //when
    boolean expiredTokenValid = jwtTokenProvider.validateToken(expiredAccessToken);

    //then
    assertFalse(expiredTokenValid);
  }

  @Test
  @Order(6)
  @DisplayName("JWT 비정상 토큰 테스트")
  public void JWT_비정상_토큰_테스트(){
    //given
    String overAccessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjM4MTksIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2NjI1NjE5fQ.-Fy5QrC4ZCbU-swm0kVJGCLIugYwEdXy2-zy0KEtuNInVQRDx7IsA0WGBZMC0W2eYJkt95jMoQXQdI6bik-F9w";
    overAccessToken += "abcdefg"; //정상 토큰 위에 이상 문자 추가

    String nullAccessToken = null; //토큰이 Null

    //when
    boolean overTokenValid = jwtTokenProvider.validateToken(overAccessToken);
    boolean nullTokenValid = jwtTokenProvider.validateToken(nullAccessToken);

    //then
    assertFalse(overTokenValid);
    assertFalse(nullTokenValid);
  }

  @Test
  @Order(7)
  @DisplayName("JWT 엑세스토큰으로 토큰 재발급 IllegalArgumentException 테스트")
  public void JWT_엑세스토큰_토큰_재발급_IllegalArgumentException_테스트(){
    //given
    String accessToken = null;

    //when
    assertThrows(IllegalArgumentException.class, () -> {
      jwtTokenProvider.createToken(accessToken);
    });

    //then
  }

  @Test
  @Order(8)
  @DisplayName("JWT 엑세스토큰으로 토큰 재발급 MalformedJwtException 테스트")
  public void JWT_엑세스토큰_토큰_재발급_MalformedJwtException_테스트(){
    //given
    String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjM4MTksIkF1dGhvcml6YXRpb24iOi";

    //when
    assertThrows(MalformedJwtException.class, () -> {
      jwtTokenProvider.createToken(accessToken);
    });

    //then
  }

  @Test
  @Order(9)
  @DisplayName("JWT 엑세스토큰으로 토큰 재발급 테스트")
  public void JWT_엑세스토큰_토큰_재발급_테스트(){
    //given
    String accessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY2MjM4MTksIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2NjI1NjE5fQ.-Fy5QrC4ZCbU-swm0kVJGCLIugYwEdXy2-zy0KEtuNInVQRDx7IsA0WGBZMC0W2eYJkt95jMoQXQdI6bik-F9w";
    long testTime = new Date().getTime();

    //when
    TokenResponseDto result = jwtTokenProvider.createToken(accessToken);

    //then
    assertTrue(result.getAccessToken() != null && result.getAccessToken().length() > 0);
    assertTrue(result.getAccessTokenExpiresIn() >= testTime);
    assertTrue(result.getRefreshToken() != null && result.getRefreshToken().length() > 0);
    assertTrue(result.getRefreshTokenExpiresIn() >= testTime);
  }
}

Token Provider Test Result

토큰 발급 Service 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
@DisplayName("토큰 인증 Service 테스트")
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JwtAuthenticationServiceMockTests {

  @InjectMocks
  AuthenticationService authenticationService;

  @Mock
  JwtTokenProvider tokenProvider;

  @Test
  @Order(1)
  @DisplayName("인증서비스 이메일 및 권한으로 토큰 발급 테스트")
  public void 인증서비스_이메일_권한_토큰_발급_테스트(){
    //given
    String memberEmail = "test1@gmail.com";
    String memberRole = MemberRoleEnum.USER.getRole();
    long testTime = new Date().getTime();

    TokenResponseDto tokenResponseDto = new TokenResponseDto(
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA",
        1716882904479L,
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ",
        1719467704479L

    );

    Collection<? extends GrantedAuthority> authorities =
        Arrays.stream(MemberRoleEnum.USER.getRole().split(","))
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());

    Authentication authentication = new UsernamePasswordAuthenticationToken(
        "test1@gmail.com", "", authorities
    );

    when(tokenProvider.createToken(any(String.class), any(String.class))).thenReturn(tokenResponseDto);
    when(tokenProvider.getAuthentication(any(String.class))).thenReturn(authentication);

    //when
    TokenResponseDto result = authenticationService.issue(memberEmail, memberRole);

    //then
    assertTrue(result.getAccessToken() != null && result.getAccessToken().length() > 0);
    assertTrue(result.getAccessTokenExpiresIn() >= testTime);
    assertTrue(result.getRefreshToken() != null && result.getRefreshToken().length() > 0);
    assertTrue(result.getRefreshTokenExpiresIn() >= testTime);

    verify(tokenProvider, times(1)).createToken(any(String.class), any(String.class));
    verify(tokenProvider, times(1)).getAuthentication(any(String.class));
  }

  @Test
  @Order(2)
  @DisplayName("인증서비스 토큰 재발급 테스트")
  public void 인증서비스_토큰_재발급_테스트(){
    //given
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";
    String refreshToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ";

    long testTime = new Date().getTime();

    Collection<? extends GrantedAuthority> authorities =
        Arrays.stream(MemberRoleEnum.USER.getRole().split(","))
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());

    Authentication authentication = new UsernamePasswordAuthenticationToken(
        "test1@gmail.com", "", authorities
    );

    String resolveAccessToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";
    String resolveRefreshToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ";

    TokenResponseDto tokenResponseDto = new TokenResponseDto(
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA",
        1716882904479L,
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ",
        1719467704479L
    );

    when(tokenProvider.resolveToken(any(String.class))).thenReturn(resolveAccessToken);
    when(tokenProvider.getAuthentication(any(String.class))).thenReturn(authentication);
    when(tokenProvider.createToken(any(String.class))).thenReturn(tokenResponseDto);

    //when
    TokenResponseDto result = authenticationService.reIssue(accessToken, refreshToken);

    //then
    assertTrue(result.getAccessToken() != null && result.getAccessToken().length() > 0);
    assertTrue(result.getAccessTokenExpiresIn() >= testTime);
    assertTrue(result.getRefreshToken() != null && result.getRefreshToken().length() > 0);
    assertTrue(result.getRefreshTokenExpiresIn() >= testTime);

    verify(tokenProvider, times(1)).resolveToken(any(String.class));
    verify(tokenProvider, times(1)).getAuthentication(any(String.class));
    verify(tokenProvider, times(1)).createToken(any(String.class));
  }
}

Token Service Test Result

토큰 발급 Controller 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
@DisplayName("토큰 발급 Controller 테스트")
@SpringBootTest
@ActiveProfiles("local")
@AutoConfigureMockMvc
public class JwtAuthenticationControllerMockTests {

  @Autowired
  MockMvc mockMvc;

  @MockBean
  AuthenticationService authenticationService;

  @Autowired
  ObjectMapper objectMapper;

  @Test
  @Order(1)
  @DisplayName("토큰컨트롤러 토큰 발급  테스트")
  public void 토큰컨트롤러_토큰_발급_테스트() throws Exception {
    //given
    TokenResponseDto tokenResponseDto = new TokenResponseDto(
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA",
        1716882904479L,
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ",
        1719467704479L
    );

    when(authenticationService.issue(any(String.class), any(String.class))).thenReturn(tokenResponseDto);

    //when
    ResultActions actions = mockMvc.perform(
        post("/api/authentication/issue")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(tokenResponseDto))
    );

    //then
    actions
        .andExpect(status().isCreated());

  }

  @Test
  @Order(2)
  @DisplayName("토큰컨트롤러 토큰 재발급 테스트")
  public void 토큰컨트롤러_토큰_재발급_테스트() throws Exception {
    //given
    String accessToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA";
    String refreshToken = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ";

    TokenResponseDto tokenResponseDto = new TokenResponseDto(
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE2ODgyOTA0fQ.c_7tnSNqP3pY_RLZAox_DvI3h1h8h5fBXPhpaZzJihGtNTbH_TViYBspU9bT5jGXqiXqKKIIAz7usDXUgyfdnA",
        1716882904479L,
        "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUBnbWFpbC5jb20iLCJpYXQiOjE3MTY4NzU3MDQsIkF1dGhvcml6YXRpb24iOiJVU0VSIiwiZXhwIjoxNzE5NDY3NzA0fQ.-TQbgkPeAOjoKzyR80KRfuf2l08QVcUc413UGfgQLuVUUfBgVXXXVnl-gfJf0BwHiGooAuxp7eHAfnr2r0SFMQ",
        1719467704479L
    );

    when(authenticationService.reIssue(any(String.class), any(String.class))).thenReturn(tokenResponseDto);

    //when
    ResultActions actions = mockMvc.perform(
        post("/api/authentication/reissue")
            .accept(MediaType.APPLICATION_JSON)
            .header("access-token", accessToken)
            .header("refresh-token", refreshToken)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(tokenResponseDto))
    );

    //then
    actions
        .andExpect(status().isCreated());
  }
}

Token Service Test Result

자동화 문서 도구 - Swagger (Spring Doc)

Token Service Test Result

Token Service Test Result

This post is licensed under CC BY 4.0 by the author.