Skip to content

Commit 6d7f43e

Browse files
authored
Merge pull request #240 from prgrms-web-devcourse-final-project/feature/badword-delete(WR9-138)
Feature/badword delete(wr9 138)
2 parents bfe3c5e + 3cf5ecc commit 6d7f43e

File tree

4 files changed

+72
-15
lines changed

4 files changed

+72
-15
lines changed

src/main/java/io/crops/warmletter/domain/badword/controller/BadWordController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ public ResponseEntity<BaseResponse<UpdateBadWordResponse>> updateBadWord(
5959
return ResponseEntity.ok(BaseResponse.of(response, "금칙어 변경 성공"));
6060
}
6161

62+
@DeleteMapping("/{badwordId}")
63+
public ResponseEntity<BaseResponse<String>> deleteBadWord(@PathVariable("badwordId") Long badWordId) {
64+
badWordService.deleteBadWord(badWordId);
65+
return ResponseEntity.ok(BaseResponse.of(null, "금칙어 영구삭제"));
66+
}
6267
}

src/main/java/io/crops/warmletter/domain/badword/service/BadWordService.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public class BadWordService {
2929
private final RedisTemplate<String, String> redisTemplate; // Redis 추가
3030

3131
private static final String BAD_WORD_KEY = "bad_word";
32-
private static final String BAD_WORD_PATTERN = "[^가-힣a-zA-Z0-9\\s]";
32+
33+
private static final String BAD_WORD_PATTERN = "[^가-힣ㄱ-ㅎㅏ-ㅣa-zA-Z0-9\\s]";
34+
3335

3436
public void createBadWord(CreateBadWordRequest request) {
3537
String word = request.getWord();
@@ -96,6 +98,18 @@ public UpdateBadWordResponse updateBadWord(Long id, UpdateBadWordRequest request
9698
return new UpdateBadWordResponse(badWord.getWord());
9799
}
98100

101+
@Transactional
102+
public void deleteBadWord(Long id) {
103+
BadWord badWord = badWordRepository.findById(id)
104+
.orElseThrow(BadWordNotFoundException:: new);
105+
106+
badWordRepository.delete(badWord);
107+
108+
redisTemplate.opsForHash().delete(BAD_WORD_KEY, id.toString());
109+
}
110+
111+
112+
99113
//필터링
100114
public void validateText(String text) {
101115
// Redis에서 금칙어 데이터를 불러옴
@@ -118,7 +132,6 @@ public void validateText(String text) {
118132

119133
// 아호코라식 트리로 텍스트를 검사
120134
Collection<Emit> matches = badWordTrie.parseText(sanitizedText);
121-
122135
// 금칙어가 발견되면 예외를 던짐
123136
if (!matches.isEmpty()) {
124137
throw new BadWordContainsException();

src/test/java/io/crops/warmletter/domain/badword/controller/BadWordControllerTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.springframework.boot.test.context.SpringBootTest;
1414
import org.springframework.context.annotation.Import;
1515
import org.springframework.http.MediaType;
16+
import static org.mockito.Mockito.doNothing;
1617

1718
import org.springframework.test.context.ActiveProfiles;
1819
import org.springframework.test.context.bean.override.mockito.MockitoBean;
@@ -139,4 +140,18 @@ void updateBadWord_ReturnsCorrectResponse() throws Exception {
139140
.andExpect(jsonPath("$.message").value("금칙어 변경 성공"));
140141
}
141142

143+
@Test
144+
@DisplayName("금칙어 영구삭제 컨트롤러 테스트 - 성공")
145+
void deleteBadWord_Success() throws Exception {
146+
// 테스트용 금칙어 id
147+
Long badwordId = 1L;
148+
149+
// badWordService.deleteBadWord(badwordId) 호출 시 아무 작업도 하지 않도록 설정
150+
doNothing().when(badWordService).deleteBadWord(badwordId);
151+
152+
// DELETE 요청을 보내고, 응답 상태와 메시지 검증
153+
mockMvc.perform(delete("/api/bad-words/{badwordId}", badwordId))
154+
.andExpect(status().isOk())
155+
.andExpect(jsonPath("$.message").value("금칙어 영구삭제"));
156+
}
142157
}

src/test/java/io/crops/warmletter/domain/badword/service/BadWordServiceTest.java

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.crops.warmletter.domain.badword.service;
22

33
import io.crops.warmletter.config.TestConfig;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
45
import io.crops.warmletter.domain.badword.dto.request.CreateBadWordRequest;
56
import io.crops.warmletter.domain.badword.dto.request.UpdateBadWordRequest;
67
import io.crops.warmletter.domain.badword.dto.request.UpdateBadWordStatusRequest;
@@ -280,26 +281,49 @@ void updateBadWord_success_withoutRedisUpdate() {
280281
}
281282

282283
@Test
283-
@DisplayName("금칙어가 포함된 경우")
284+
@DisplayName("deleteBadWord - 성공 케이스: 존재하는 금칙어 삭제")
285+
void deleteBadWord_success() {
286+
// given
287+
Long badWordId = 1L;
288+
BadWord badWord = new BadWord();
289+
// 필요한 경우 badWord에 속성을 추가할 수 있습니다.
290+
when(badWordRepository.findById(badWordId)).thenReturn(Optional.of(badWord));
291+
292+
// when
293+
badWordService.deleteBadWord(badWordId);
294+
295+
// then: 리포지토리에서 delete() 메서드 호출 및 Redis에서 삭제 호출 검증
296+
verify(badWordRepository).delete(badWord);
297+
verify(hashOperations).delete(BAD_WORD_KEY, badWordId.toString());
298+
}
299+
300+
@Test
301+
@DisplayName("deleteBadWord - 실패 케이스: 존재하지 않는 금칙어 삭제 시 예외 발생")
302+
void deleteBadWord_notFound() {
303+
// given
304+
Long badWordId = 2L;
305+
when(badWordRepository.findById(badWordId)).thenReturn(Optional.empty());
306+
307+
// when & then: BadWordNotFoundException 발생 검증
308+
assertThrows(BadWordNotFoundException.class, () -> badWordService.deleteBadWord(badWordId));
309+
}
310+
311+
@Test
312+
@DisplayName("금칙어가 포함된 경우 - 예외 발생")
284313
void testValidateTextWithBadWord() {
285-
// 금칙어를 포함한 문자열 설정
286-
// 금칙어가 독립적인 단어로 나타나도록 수정 (예: "금칙어0" 뒤에 공백 추가)
314+
// 테스트용 텍스트: 금칙어가 독립된 단어로 존재하도록 공백을 둡니다.
287315
String targetStr = "이 문장에는 금칙어0 가 포함되어 있습니다.";
288316
System.out.println("targetStr: " + targetStr);
289317

290-
Map<Object, Object> badWords = redisTemplate.opsForHash().entries(BAD_WORD_KEY);
291-
System.out.println("Redis에서 불러온 금칙어 개수: " + badWords.size());
318+
// 해당 테스트에서 사용할 모의 금칙어 데이터: 오직 "금칙어0"만 포함
319+
Map<Object, Object> testBadWords = new HashMap<>();
320+
testBadWords.put("1", "금칙어0");
292321

293-
long startTime = System.nanoTime();
294-
// 금칙어가 있으므로 예외가 발생해야 함
295-
BadWordContainsException thrown = assertThrows(BadWordContainsException.class, () -> {
322+
// 테스트 케이스 내에서 모의 데이터를 재설정(오버라이드)합니다.
323+
when(hashOperations.entries(BAD_WORD_KEY)).thenReturn(testBadWords);
324+
assertThrows(BadWordContainsException.class, () -> {
296325
badWordService.validateText(targetStr);
297326
});
298-
long endTime = System.nanoTime();
299-
double progressTime = (endTime - startTime) / 1_000_000.0;
300-
301-
System.out.println("테스트 완료! 실행 시간: " + progressTime + "ms");
302-
System.out.println("예외 메시지: " + thrown.getMessage());
303327
}
304328

305329
@Test

0 commit comments

Comments
 (0)