-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPostServiceTest.java
More file actions
278 lines (235 loc) · 10.2 KB
/
PostServiceTest.java
File metadata and controls
278 lines (235 loc) · 10.2 KB
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
package com.rentify.rentify_api.post.service;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.rentify.rentify_api.category.entity.Category;
import com.rentify.rentify_api.category.exception.CategoryNotFoundException;
import com.rentify.rentify_api.category.repository.CategoryRepository;
import com.rentify.rentify_api.common.exception.IdempotencyException;
import com.rentify.rentify_api.common.exception.NotFoundException;
import com.rentify.rentify_api.common.idempotency.IdempotencyKey;
import com.rentify.rentify_api.common.idempotency.IdempotencyKeyRepository;
import com.rentify.rentify_api.common.idempotency.IdempotencyStatus;
import com.rentify.rentify_api.image.entity.Image;
import com.rentify.rentify_api.image.service.ImageService;
import com.rentify.rentify_api.post.dto.CreatePostRequest;
import com.rentify.rentify_api.post.dto.PostDetailResponse;
import com.rentify.rentify_api.post.entity.Post;
import com.rentify.rentify_api.post.repository.PostHistoryRepository;
import com.rentify.rentify_api.post.repository.PostRepository;
import com.rentify.rentify_api.user.entity.User;
import com.rentify.rentify_api.user.exception.UserNotFoundException;
import com.rentify.rentify_api.user.repository.UserRepository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class PostServiceTest {
@Mock
private IdempotencyKeyRepository idempotencyKeyRepository;
@Mock
private PostRepository postRepository;
@Mock
private UserRepository userRepository;
@Mock
private CategoryRepository categoryRepository;
@Mock
private ImageService imageService;
@Mock
private PostHistoryRepository postHistoryRepository;
@InjectMocks
private PostService postService;
private UUID idempotencyKey;
private Long userId;
private CreatePostRequest request;
@BeforeEach
void setUp() {
idempotencyKey = UUID.randomUUID();
userId = 1L;
request = new CreatePostRequest();
}
@Test
@DisplayName("게시글 생성 성공")
void create_post_success() {
// given
request.setCategoryId(1L);
request.setTitle("테스트 제목");
request.setDescription("테스트 내용");
request.setPricePerDay(1000);
request.setMaxRentalDays(10);
request.setIsParcel(true);
request.setIsMeetup(true);
request.setImageUrls(
List.of(
"http://test.com:8080/images/test1.png",
"http//test.com:8080/images/test2.jpg"
)
);
User user = User.builder()
.id(userId)
.email("test@test.com")
.name("테스트 유저")
.build();
Category category = Category.builder()
.id(request.getCategoryId())
.build();
Post savedPost = Post.builder().id(100L).build();
given(idempotencyKeyRepository.findById(idempotencyKey)).willReturn(Optional.empty());
given(userRepository.findById(userId)).willReturn(Optional.of(user));
given(categoryRepository.findById(request.getCategoryId())).willReturn(
Optional.of(category));
given(idempotencyKeyRepository.saveAndFlush(any()))
.willAnswer(invocation -> invocation.getArgument(0));
given(postRepository.save(any(Post.class))).willReturn(savedPost);
// when
Long savedPostId = postService.createPost(idempotencyKey, userId, request);
// then
assertThat(100L).isEqualTo(savedPostId);
// verify
verify(idempotencyKeyRepository, times(1)).saveAndFlush(any(IdempotencyKey.class));
verify(imageService, times(1)).saveImages(savedPost, request.getImageUrls());
verify(postHistoryRepository, times(1)).save(any());
}
@Test
@DisplayName("멱등성 확인: 이미 성공적으로 처리된 요청(키)이면 저장된 ID를 바로 반환한다.")
void create_post_idempotency_success() {
//given
Map<String, Object> responseBody = new HashMap<>();
responseBody.put("postId", 10L);
IdempotencyKey existKey = IdempotencyKey.builder()
.idempotencyKey(idempotencyKey)
.status(IdempotencyStatus.SUCCESS)
.responseBody(responseBody)
.build();
given(idempotencyKeyRepository.findById(idempotencyKey)).willReturn(Optional.of(existKey));
// when
Long postId = postService.createPost(idempotencyKey, userId, request);
// then
assertThat(10L).isEqualTo(postId);
// verify
verify(idempotencyKeyRepository, times(0)).saveAndFlush(any());
verify(postHistoryRepository, times(0)).save(any());
verify(imageService, times(0)).saveImages(any(), any());
verify(postRepository, times(0)).save(any());
}
@Test
@DisplayName("멱등성 처리 예외 발생")
void create_post_idempotency_pending() {
//given
IdempotencyKey pendingKey = IdempotencyKey.builder()
.idempotencyKey(idempotencyKey)
.status(IdempotencyStatus.PENDING)
.build();
given(idempotencyKeyRepository.findById(idempotencyKey)).willReturn(
Optional.of(pendingKey));
// when & then
assertThatThrownBy(() -> postService.createPost(idempotencyKey, userId, request))
.isInstanceOf(IdempotencyException.class)
.hasMessage("이전 게시글이 생성 중 입니다. 잠시 후 결과를 확인해주세요.");
// verify
verify(idempotencyKeyRepository, times(0)).saveAndFlush(any());
}
@Test
@DisplayName("존재하지 않는 유저 예외")
void create_post_user_notfound() {
// given
Long notFoundUserId = Long.MAX_VALUE;
given(idempotencyKeyRepository.findById(idempotencyKey)).willReturn(Optional.empty());
given(idempotencyKeyRepository.saveAndFlush(any())).willAnswer(
invocation -> invocation.getArgument(0));
given(userRepository.findById(notFoundUserId)).willReturn(Optional.empty());
// when & then
assertThatThrownBy(() -> postService.createPost(idempotencyKey, notFoundUserId, request))
.isInstanceOf(UserNotFoundException.class);
// verify
verify(idempotencyKeyRepository, times(1)).saveAndFlush(any());
verify(imageService, times(0)).saveImages(any(), any());
verify(postHistoryRepository, times(0)).save(any());
verify(postRepository, times(0)).save(any());
}
@Test
@DisplayName("존재하지 않는 카테고리 오류")
void create_post_category_notfound() {
// given
given(idempotencyKeyRepository.findById(idempotencyKey)).willReturn(Optional.empty());
given(idempotencyKeyRepository.saveAndFlush(any())).willAnswer(
invocation -> invocation.getArgument(0));
given(userRepository.findById(userId)).willReturn(Optional.of(User.builder().build()));
given(categoryRepository.findById(request.getCategoryId())).willReturn(Optional.empty());
// when & then
assertThatThrownBy(() -> postService.createPost(idempotencyKey, userId, request))
.isInstanceOf(CategoryNotFoundException.class)
.hasMessage("등록되지 않은 카테고리입니다.");
// verify
verify(idempotencyKeyRepository, times(1)).saveAndFlush(any());
verify(imageService, times(0)).saveImages(any(), any());
verify(postHistoryRepository, times(0)).save(any());
verify(postRepository, times(0)).save(any());
}
@Test
@DisplayName("게시글 상세 조회 성공")
void get_post_success() {
// given
Long postId = 1L;
User mockUser = User.builder()
.id(100L)
.name("테스트유저")
.build();
Category mockCategory = Category.builder()
.id(200L)
.name("전자기기")
.build();
Image mockImage1 = Image.builder().url("http://test.com/1.jpg").build();
Image mockImage2 = Image.builder().url("http://test.com/2.jpg").build();
Post mockPost = Post.builder()
.id(postId)
.title("테스트 제목")
.description("테스트 내용")
.pricePerDay(5000)
.maxRentalDays(5)
.isParcel(true)
.images(List.of(mockImage1, mockImage2))
.user(mockUser)
.category(mockCategory)
.build();
given(postRepository.findById(postId)).willReturn(Optional.of(mockPost));
// when
PostDetailResponse response = postService.getPost(postId);
// then
assertThat(response.getPostId()).isEqualTo(postId);
assertThat(response.getTitle()).isEqualTo("테스트 제목");
assertThat(response.getUserId()).isEqualTo(100L);
assertThat(response.getUserName()).isEqualTo("테스트유저");
assertThat(response.getCategoryName()).isEqualTo("전자기기");
assertThat(response.getImageUrls()).hasSize(2);
assertThat(response.getImageUrls()).containsExactly(
"http://test.com/1.jpg",
"http://test.com/2.jpg"
);
// verify
verify(postRepository, times(1)).findById(any());
}
@Test
@DisplayName("게시글 상세 조회 실패")
void get_post_notfound() {
// given
Long invalidPostId = 10L;
given(postRepository.findById(invalidPostId)).willReturn(Optional.empty());
// when & then
assertThatThrownBy(() -> postService.getPost(invalidPostId))
.isInstanceOf(NotFoundException.class)
.hasMessage("게시글을 찾을 수 없습니다.");
}
}