Divide AnswerService independently

This commit is contained in:
MangKyu
2023-02-18 17:08:03 +09:00
parent 6dfe5f531b
commit c0955737e4
15 changed files with 204 additions and 73 deletions

View File

@@ -1,6 +1,6 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.UpdateAnswerService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@@ -13,7 +13,7 @@ import javax.validation.Valid;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AddAnswerController { public class AddAnswerController {
private final AnswerService answerService; private final UpdateAnswerService answerService;
@PostMapping("/answers") @PostMapping("/answers")
public ResponseEntity<Void> postAnswer(@RequestBody @Valid final AddAnswerRequest addAnswerRequest) { public ResponseEntity<Void> postAnswer(@RequestBody @Valid final AddAnswerRequest addAnswerRequest) {

View File

@@ -1,7 +1,6 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.DeleteAnswerService;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
@@ -12,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor @RequiredArgsConstructor
public class DeleteAnswerController { public class DeleteAnswerController {
private final AnswerService answerService; private final DeleteAnswerService answerService;
@DeleteMapping("/answers/{resourceId}") @DeleteMapping("/answers/{resourceId}")
public ResponseEntity<Void> deleteAnswer(@PathVariable final String resourceId) { public ResponseEntity<Void> deleteAnswer(@PathVariable final String resourceId) {

View File

@@ -1,6 +1,6 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor @RequiredArgsConstructor
public class GetAnswerController { public class GetAnswerController {
private final AnswerService answerService; private final GetAnswerService answerService;
@GetMapping("/answers/{resourceId}") @GetMapping("/answers/{resourceId}")
public ResponseEntity<GetAnswerResponse> getAnswer(@PathVariable final String resourceId) { public ResponseEntity<GetAnswerResponse> getAnswer(@PathVariable final String resourceId) {

View File

@@ -1,6 +1,7 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import com.mangkyu.employment.interview.app.answer.service.UpdateAnswerService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
@@ -13,7 +14,7 @@ import javax.validation.Valid;
@RequiredArgsConstructor @RequiredArgsConstructor
public class UpdateAnswerController { public class UpdateAnswerController {
private final AnswerService answerService; private final UpdateAnswerService answerService;
@PutMapping("/answers") @PutMapping("/answers")
public ResponseEntity<Void> putAnswer(@RequestBody @Valid final AddAnswerRequest addAnswerRequest) { public ResponseEntity<Void> putAnswer(@RequestBody @Valid final AddAnswerRequest addAnswerRequest) {

View File

@@ -0,0 +1,26 @@
package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class DeleteAnswerService {
private final AnswerRepository answerRepository;
@Transactional
public void deleteAnswer(final String resourceId) throws RestApiException {
final Answer answer = answerRepository.findByResourceId(resourceId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));
answer.getQuiz().setAnswer(null);
answerRepository.delete(answer);
}
}

View File

@@ -0,0 +1,27 @@
package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.app.quiz.converter.QuizDtoConverter;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GetAnswerService {
private final AnswerRepository answerRepository;
public GetAnswerResponse getAnswer(final String resourceId) throws RestApiException {
final Answer answer = answerRepository.findByResourceId(resourceId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));
return QuizDtoConverter.convert(answer);
}
}

View File

@@ -1,11 +1,8 @@
package com.mangkyu.employment.interview.app.answer.service; package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest; import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.entity.Answer; import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository; import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import com.mangkyu.employment.interview.app.quiz.converter.QuizDtoConverter; import com.mangkyu.employment.interview.app.quiz.converter.QuizDtoConverter;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz; import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.service.QuizService; import com.mangkyu.employment.interview.app.quiz.service.QuizService;
@@ -16,20 +13,13 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@Transactional(readOnly = true) @Transactional(readOnly = true)
public class AnswerService { public class UpdateAnswerService {
private final QuizService quizService; private final QuizService quizService;
private final AnswerRepository answerRepository; private final AnswerRepository answerRepository;
public GetAnswerResponse getAnswer(final String resourceId) throws RestApiException {
final Answer answer = answerRepository.findByResourceId(resourceId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));
return QuizDtoConverter.convert(answer);
}
@Transactional @Transactional
public void addAnswer(final AddAnswerRequest addAnswerRequest) throws RestApiException { public void addAnswer(final AddAnswerRequest addAnswerRequest) {
final Quiz quiz = quizService.findQuiz(addAnswerRequest.getQuizResourceId()); final Quiz quiz = quizService.findQuiz(addAnswerRequest.getQuizResourceId());
final Answer quizAnswer = quiz.getAnswer(); final Answer quizAnswer = quiz.getAnswer();
if (quizAnswer == null) { if (quizAnswer == null) {
@@ -41,11 +31,4 @@ public class AnswerService {
} }
} }
@Transactional
public void deleteAnswer(final String resourceId) throws RestApiException {
final Answer answer = answerRepository.findByResourceId(resourceId)
.orElseThrow(() -> new RestApiException(CommonErrorCode.RESOURCE_NOT_FOUND));
answer.getQuiz().setAnswer(null);
answerRepository.delete(answer);
}
} }

View File

@@ -1,7 +1,7 @@
package com.mangkyu.employment.interview.app.quiz.controller; package com.mangkyu.employment.interview.app.quiz.controller;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse; import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import com.mangkyu.employment.interview.app.quiz.dto.GetQuizResponse; import com.mangkyu.employment.interview.app.quiz.dto.GetQuizResponse;
import com.mangkyu.employment.interview.app.quiz.service.QuizService; import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.PathVariable;
public class WebQuizController { public class WebQuizController {
private final QuizService quizService; private final QuizService quizService;
private final AnswerService answerService; private final GetAnswerService answerService;
@GetMapping("/quiz/editView/{resourceId}") @GetMapping("/quiz/editView/{resourceId}")
public String addUserPage(@PathVariable final String resourceId, final Model model) { public String addUserPage(@PathVariable final String resourceId, final Model model) {

View File

@@ -1,7 +1,7 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@@ -25,7 +25,7 @@ class AddAnswerControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Autowired @Autowired
private AnswerService answerService; private GetAnswerService answerService;
@ParameterizedTest @ParameterizedTest
@MethodSource("provideParameters") @MethodSource("provideParameters")

View File

@@ -1,6 +1,6 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
@@ -19,7 +19,7 @@ class DeleteAnswerControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Autowired @Autowired
private AnswerService answerService; private GetAnswerService answerService;
@Test @Test
public void deleteAnswerSuccess() throws Exception { public void deleteAnswerSuccess() throws Exception {

View File

@@ -1,6 +1,6 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
@@ -21,7 +21,7 @@ class GetAnswerControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Autowired @Autowired
private AnswerService answerService; private GetAnswerService answerService;
@Test @Test
public void getAnswer() throws Exception { public void getAnswer() throws Exception {

View File

@@ -1,7 +1,7 @@
package com.mangkyu.employment.interview.app.answer.controller; package com.mangkyu.employment.interview.app.answer.controller;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.mangkyu.employment.interview.app.answer.service.AnswerService; import com.mangkyu.employment.interview.app.answer.service.GetAnswerService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@@ -25,7 +25,7 @@ class UpdateAnswerControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Autowired @Autowired
private AnswerService answerService; private GetAnswerService answerService;
@ParameterizedTest @ParameterizedTest
@MethodSource("provideParameters") @MethodSource("provideParameters")

View File

@@ -0,0 +1,63 @@
package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import com.mangkyu.employment.interview.testutils.EntityCreationUtils;
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;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Optional;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class DeleteAnswerServiceTest {
@InjectMocks
private DeleteAnswerService answerService;
@Mock
private AnswerRepository answerRepository;
@Test
public void deleteAnswerByQuizResourceIdFail_AnswerNotExists() {
// given
final String resourceId = UUID.randomUUID().toString();
doReturn(Optional.empty()).when(answerRepository).findByResourceId(resourceId);
// when
final RestApiException result = assertThrows(RestApiException.class, () -> answerService.deleteAnswer(resourceId));
// then
assertThat(result.getErrorCode()).isEqualTo(CommonErrorCode.RESOURCE_NOT_FOUND);
}
@Test
public void deleteAnswerByQuizResourceIdSuccess() throws RestApiException {
// given
final Quiz quiz = EntityCreationUtils.quiz();
final Answer answer = EntityCreationUtils.answer(quiz);
doReturn(Optional.of(answer)).when(answerRepository).findByResourceId(answer.getResourceId());
// when
answerService.deleteAnswer(answer.getResourceId());
// then
// verify
verify(answerRepository, times(1)).delete(answer);
}
}

View File

@@ -0,0 +1,64 @@
package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.testutils.EntityCreationUtils;
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;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Optional;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class GetAnswerServiceTest {
@InjectMocks
private GetAnswerService answerService;
@Mock
private QuizService quizService;
@Mock
private AnswerRepository answerRepository;
@Test
public void getAnswerByQuizResourceIdFail_AnswerNotExists() {
// given
final String resourceId = UUID.randomUUID().toString();
doReturn(Optional.empty()).when(answerRepository).findByResourceId(resourceId);
// when
final RestApiException result = assertThrows(RestApiException.class, () -> answerService.getAnswer(resourceId));
// then
assertThat(result.getErrorCode()).isEqualTo(CommonErrorCode.RESOURCE_NOT_FOUND);
}
@Test
public void getAnswerByQuizResourceIdSuccess() throws RestApiException {
// given
final Quiz quiz = EntityCreationUtils.quiz();
final Answer answer = EntityCreationUtils.answer(quiz);
doReturn(Optional.of(answer)).when(answerRepository).findByResourceId(answer.getResourceId());
// when
final GetAnswerResponse result = answerService.getAnswer(answer.getResourceId());
// then
assertThat(result.getDescription()).isEqualTo(answer.getDescription());
}
}

View File

@@ -1,13 +1,11 @@
package com.mangkyu.employment.interview.app.answer.service; package com.mangkyu.employment.interview.app.answer.service;
import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest; import com.mangkyu.employment.interview.app.answer.controller.AddAnswerRequest;
import com.mangkyu.employment.interview.app.answer.controller.GetAnswerResponse;
import com.mangkyu.employment.interview.app.answer.entity.Answer; import com.mangkyu.employment.interview.app.answer.entity.Answer;
import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository; import com.mangkyu.employment.interview.app.answer.repository.AnswerRepository;
import com.mangkyu.employment.interview.erros.errorcode.CommonErrorCode;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz; import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.service.QuizService; import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.erros.exception.RestApiException;
import com.mangkyu.employment.interview.testutils.EntityCreationUtils; import com.mangkyu.employment.interview.testutils.EntityCreationUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -16,18 +14,15 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class AnswerServiceTest { class UpdateAnswerServiceTest {
@InjectMocks @InjectMocks
private AnswerService answerService; private UpdateAnswerService answerService;
@Mock @Mock
private QuizService quizService; private QuizService quizService;
@@ -74,31 +69,4 @@ class AnswerServiceTest {
verify(answerRepository, times(1)).save(any(Answer.class)); verify(answerRepository, times(1)).save(any(Answer.class));
} }
@Test
public void getAnswerByQuizResourceIdFail_AnswerNotExists() {
// given
final String resourceId = UUID.randomUUID().toString();
doReturn(Optional.empty()).when(answerRepository).findByResourceId(resourceId);
// when
final RestApiException result = assertThrows(RestApiException.class, () -> answerService.getAnswer(resourceId));
// then
assertThat(result.getErrorCode()).isEqualTo(CommonErrorCode.RESOURCE_NOT_FOUND);
}
@Test
public void getAnswerByQuizResourceIdSuccess() throws RestApiException {
// given
final Quiz quiz = EntityCreationUtils.quiz();
final Answer answer = EntityCreationUtils.answer(quiz);
doReturn(Optional.of(answer)).when(answerRepository).findByResourceId(answer.getResourceId());
// when
final GetAnswerResponse result = answerService.getAnswer(answer.getResourceId());
// then
assertThat(result.getDescription()).isEqualTo(answer.getDescription());
}
} }