Merge branch 'master' into master-web

This commit is contained in:
MangKyu
2021-12-27 23:19:11 +09:00
16 changed files with 325 additions and 103 deletions

View File

@@ -0,0 +1,34 @@
package com.mangkyu.employment.interview.app.enums.controller;
import com.mangkyu.employment.interview.enums.common.EnumMapperKey;
import com.mangkyu.employment.interview.enums.common.EnumMapperValue;
import com.mangkyu.employment.interview.enums.factory.EnumMapperFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class EnumsController {
private final EnumMapperFactory enumMapperFactory;
@GetMapping("/enums/quiz/category")
public ResponseEntity<List<EnumMapperValue>> getQuizCategoryList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_CATEGORY));
}
@GetMapping("/enums/quiz/level")
public ResponseEntity<List<EnumMapperValue>> getQuizLevelList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_LEVEL));
}
@GetMapping("/enums/quiz/day")
public ResponseEntity<List<EnumMapperValue>> getQuizDayList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_DAY));
}
}

View File

@@ -3,6 +3,8 @@ package com.mangkyu.employment.interview.app.quiz.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mangkyu.employment.interview.app.quiz.dto.AddQuizRequest;
import com.mangkyu.employment.interview.app.quiz.dto.AddQuizRequestHolder;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponse;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponseHolder;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.enums.common.EnumMapperKey;
import com.mangkyu.employment.interview.enums.common.EnumMapperValue;
@@ -20,12 +22,12 @@ import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequiredArgsConstructor
public class QuizController {
private final EnumMapperFactory enumMapperFactory;
private final QuizService quizService;
@GetMapping("/quiz/init")
@@ -48,18 +50,11 @@ public class QuizController {
}
@GetMapping("/quiz/category")
public ResponseEntity<List<EnumMapperValue>> getQuizCategoryList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_CATEGORY));
}
@GetMapping("/quiz/level")
public ResponseEntity<List<EnumMapperValue>> getQuizLevelList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_LEVEL));
}
@GetMapping("/quiz/day")
public ResponseEntity<List<EnumMapperValue>> getQuizDayList() {
return ResponseEntity.ok(enumMapperFactory.get(EnumMapperKey.QUIZ_DAY));
public ResponseEntity<QuizCategoryResponseHolder> getQuizCategoryList() {
final QuizCategoryResponseHolder response = QuizCategoryResponseHolder.builder()
.categoryList(quizService.getQuizCategoryList())
.build();
return ResponseEntity.ok(response);
}
}

View File

@@ -0,0 +1,17 @@
package com.mangkyu.employment.interview.app.quiz.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@Builder
@RequiredArgsConstructor
public class QuizCategoryResponse {
private final long count;
private final String code;
private final String title;
private final String desc;
}

View File

@@ -0,0 +1,16 @@
package com.mangkyu.employment.interview.app.quiz.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.List;
@Getter
@Builder
@RequiredArgsConstructor
public class QuizCategoryResponseHolder {
private final List<QuizCategoryResponse> categoryList;
}

View File

@@ -10,6 +10,8 @@ import java.util.Set;
public interface QuizRepository extends JpaRepository<Quiz, Long> {
Long countByQuizCategory(final QuizCategory category);
default List<Quiz> customFindByIdNotInAndQuizLevel(final Set<Long> quizIdSet, final QuizLevel quizLevel) {
return quizIdSet.isEmpty()
? findByQuizLevel(quizLevel)

View File

@@ -1,9 +1,13 @@
package com.mangkyu.employment.interview.app.quiz.service;
import com.mangkyu.employment.interview.app.quiz.dto.AddQuizRequest;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponse;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.repository.QuizRepository;
import com.mangkyu.employment.interview.app.solvedquiz.repository.SolvedQuizRepository;
import com.mangkyu.employment.interview.enums.common.EnumMapperKey;
import com.mangkyu.employment.interview.enums.common.EnumMapperValue;
import com.mangkyu.employment.interview.enums.factory.EnumMapperFactory;
import com.mangkyu.employment.interview.enums.value.QuizCategory;
import com.mangkyu.employment.interview.enums.value.QuizLevel;
import lombok.RequiredArgsConstructor;
@@ -22,9 +26,10 @@ import java.util.stream.Collectors;
@Transactional(readOnly = true)
public class QuizService {
private final ModelMapper modelMapper;
private final QuizRepository quizRepository;
private final SolvedQuizRepository solvedQuizRepository;
private final ModelMapper modelMapper;
private final EnumMapperFactory enumMapperFactory;
@Transactional
public void addQuiz(final AddQuizRequest addQuizRequest) {
@@ -61,4 +66,19 @@ public class QuizService {
return randomQuizList;
}
public List<QuizCategoryResponse> getQuizCategoryList() {
final List<EnumMapperValue> enumMapperValueList = enumMapperFactory.get(EnumMapperKey.QUIZ_CATEGORY);
return enumMapperValueList.stream()
.map(this::convertToQuizCategoryResponse)
.collect(Collectors.toList());
}
private QuizCategoryResponse convertToQuizCategoryResponse(final EnumMapperValue enumMapperValue) {
return QuizCategoryResponse.builder()
.count(quizRepository.countByQuizCategory(QuizCategory.valueOf(enumMapperValue.name())))
.code(enumMapperValue.getCode())
.title(enumMapperValue.getTitle())
.desc(enumMapperValue.getDesc())
.build();
}
}

View File

@@ -2,7 +2,9 @@ package com.mangkyu.employment.interview.enums.common;
public interface EnumMapperType {
String getCode();
String name();
String getTitle();
String getDesc();

View File

@@ -1,21 +1,21 @@
package com.mangkyu.employment.interview.enums.common;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@Builder
@RequiredArgsConstructor
public class EnumMapperValue implements EnumMapperType {
private final String code;
private final String title;
private final String desc;
@Override
public String getCode() {
public String name() {
return code;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@@ -25,8 +25,16 @@ public class EnumMapperFactory {
private List<EnumMapperValue> createEnumMapperValueList(final Class<? extends EnumMapperType> e) {
return Arrays.stream(e.getEnumConstants())
.map(v -> new EnumMapperValue(v.getCode(), v.getDesc()))
.map(this::convertToEnumMapperValue)
.collect(Collectors.toList());
}
private EnumMapperValue convertToEnumMapperValue(final EnumMapperType enumMapperType) {
return EnumMapperValue.builder()
.code(enumMapperType.name())
.title(enumMapperType.getTitle())
.desc(enumMapperType.getDesc())
.build();
}
}

View File

@@ -8,25 +8,22 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum QuizCategory implements EnumMapperType {
JAVA("Java"),
SPRING("Spring Framework"),
SERVER("Server Side Programming"),
NETWORK("Network"),
OPERATING_SYSTEM("Operating System"),
DATABASE("Database"),
PROGRAMMING("Overall Programming"),
DATA_STRUCTURE("Data Structure"),
ALGORITHM("Database"),
PROBLEM_SOLVING("Problem Solving"),
CULTURE("Culture Fit"),
EXPERIENCE("Personal Experience"),
PERSONALITY("About Interviewee"),
;
JAVA("Java", "Java 언어와 관련된 면접 질문을 살펴보세요"),
SPRING("Spring Framework", "Spring 프레임워크와 관련된 면접 질문을 살펴보세요"),
SERVER("Server Programming", "서버 프로그래밍 관련된 면접 질문을 살펴보세요"),
NETWORK("Network", "네트워크와 관련된 면접 질문을 살펴보세요"),
OPERATING_SYSTEM("Operating System", "운영체제와 관련된 면접 질문을 살펴보세요"),
DATABASE("Database", "데이터베이스와 관련된 면접 질문을 살펴보세요"),
PROGRAMMING("Overall Programming", "전반적인 프로그래밍과 관련된 면접 질문을 살펴보세요"),
DATA_STRUCTURE("Data Structure", "자료구조와 관련된 면접 질문을 살펴보세요"),
ALGORITHM("Database", "알고리즘과 관련된 면접 질문을 살펴보세요"),
PROBLEM_SOLVING("Problem Solving", "문제 해결과 관련된 면접 질문을 살펴보세요"),
CULTURE("Culture Fit", "문화 적합도와 관련된 면접 질문을 살펴보세요"),
EXPERIENCE("Personal Experience", "개인의 경험와 관련된 면접 질문을 살펴보세요"),
PERSONALITY("Personality", "개인의 성향과 관련된 면접 질문을 살펴보세요"),
;
private final String desc;
private final String title;
private final String desc;
@Override
public String getCode() {
return name();
}
}

View File

@@ -11,23 +11,19 @@ import java.util.Arrays;
@RequiredArgsConstructor
public enum QuizDay implements EnumMapperType {
MONDAY("Monday", DayOfWeek.MONDAY),
TUESDAY("Tuesday", DayOfWeek.TUESDAY),
WEDNESDAY("Wednesday", DayOfWeek.WEDNESDAY),
THURSDAY("Thursday", DayOfWeek.THURSDAY),
FRIDAY("Friday", DayOfWeek.FRIDAY),
SATURDAY("Saturday", DayOfWeek.SATURDAY),
SUNDAY("Sunday", DayOfWeek.SUNDAY),
MONDAY("Monday", "월요일", DayOfWeek.MONDAY),
TUESDAY("Tuesday", "화요일", DayOfWeek.TUESDAY),
WEDNESDAY("Wednesday", "수요일", DayOfWeek.WEDNESDAY),
THURSDAY("Thursday", "목요일", DayOfWeek.THURSDAY),
FRIDAY("Friday", "금요일", DayOfWeek.FRIDAY),
SATURDAY("Saturday", "토요일", DayOfWeek.SATURDAY),
SUNDAY("Sunday", "일요일", DayOfWeek.SUNDAY),
;
private final String title;
private final String desc;
private final DayOfWeek dayOfWeek;
@Override
public String getCode() {
return name();
}
public static QuizDay findQuizDay(final DayOfWeek dayOfWeek) {
return Arrays.stream(QuizDay.values())
.filter(v -> v.dayOfWeek == dayOfWeek)

View File

@@ -8,15 +8,12 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum QuizLevel implements EnumMapperType {
NEW("New Developers"),
JUNIOR("Junior Developers"),
SENIOR("Senior Developers"),
;
NEW("New Developers", "신입"),
JUNIOR("Junior Developers", "주니어"),
SENIOR("Senior Developers", "시니어"),
;
private final String desc;
private final String title;
private final String desc;
@Override
public String getCode() {
return name();
}
}

View File

@@ -0,0 +1,89 @@
package com.mangkyu.employment.interview.app.enums.controller;
import com.google.gson.Gson;
import com.mangkyu.employment.interview.config.enums.EnumMapperConfig;
import com.mangkyu.employment.interview.enums.factory.EnumMapperFactory;
import com.mangkyu.employment.interview.enums.value.QuizCategory;
import com.mangkyu.employment.interview.enums.value.QuizDay;
import com.mangkyu.employment.interview.enums.value.QuizLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(MockitoExtension.class)
class EnumsControllerTest {
@InjectMocks
private EnumsController target;
@Spy
private EnumMapperFactory enumMapperFactory = new EnumMapperConfig().enumMapperFactory();
private MockMvc mockMvc;
@BeforeEach
public void init() {
mockMvc = MockMvcBuilders.standaloneSetup(target).build();
}
@Test
public void getEnumsQuizCategoryList() throws Exception {
// given
final String url = "/enums/quiz/category";
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizCategory.values().length);
}
@Test
public void getEnumsQuizLevelList() throws Exception {
// given
final String url = "/enums/quiz/level";
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizLevel.values().length);
}
@Test
public void getEnumsQuizDayList() throws Exception {
// given
final String url = "/enums/quiz/day";
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizDay.values().length);
}
}

View File

@@ -2,18 +2,16 @@ package com.mangkyu.employment.interview.app.quiz.controller;
import com.google.gson.Gson;
import com.mangkyu.employment.interview.app.quiz.dto.AddQuizRequest;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponse;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponseHolder;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.config.enums.EnumMapperConfig;
import com.mangkyu.employment.interview.enums.factory.EnumMapperFactory;
import com.mangkyu.employment.interview.enums.value.QuizCategory;
import com.mangkyu.employment.interview.enums.value.QuizDay;
import com.mangkyu.employment.interview.enums.value.QuizLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@@ -22,9 +20,9 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(MockitoExtension.class)
@@ -35,8 +33,6 @@ class QuizControllerTest {
@Mock
private QuizService quizService;
@Spy
private EnumMapperFactory enumMapperFactory = new EnumMapperConfig().enumMapperFactory();
private MockMvc mockMvc;
@@ -68,9 +64,19 @@ class QuizControllerTest {
}
@Test
public void getQuizCategoryListSuccess() throws Exception {
public void getQuizCategory() throws Exception {
// given
final String url = "/quiz/category";
final long count = 15L;
final QuizCategoryResponse quizCategoryResponse = QuizCategoryResponse.builder()
.count(count)
.code(QuizCategory.JAVA.name())
.title(QuizCategory.JAVA.getTitle())
.desc(QuizCategory.JAVA.getDesc())
.build();
doReturn(Collections.singletonList(quizCategoryResponse)).when(quizService).getQuizCategoryList();
// when
final ResultActions result = mockMvc.perform(
@@ -80,39 +86,9 @@ class QuizControllerTest {
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizCategory.values().length);
}
@Test
public void getQuizLevelListSuccess() throws Exception {
// given
final String url = "/quiz/level";
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizLevel.values().length);
}
@Test
public void getQuizDaySuccess() throws Exception {
// given
final String url = "/quiz/day";
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);
// then
final ResultActions resultActions = result.andExpect(status().isOk());
final String stringResponse = resultActions.andReturn().getResponse().getContentAsString();
assertThat(new Gson().fromJson(stringResponse, List.class).size()).isEqualTo(QuizDay.values().length);
final QuizCategoryResponseHolder responseHolder = new Gson().fromJson(stringResponse, QuizCategoryResponseHolder.class);
assertThat(responseHolder.getCategoryList().size()).isEqualTo(1);
assertThat(responseHolder.getCategoryList().get(0).getCount()).isEqualTo(count);
}
}

View File

@@ -17,6 +17,44 @@ class QuizRepositoryTest {
@Autowired
private QuizRepository quizRepository;
@Test
public void selectQuizCountByCategory() {
// given
final Quiz quiz1 = Quiz.builder()
.title("quiz1")
.quizCategory(QuizCategory.JAVA)
.quizLevel(Arrays.asList(QuizLevel.NEW, QuizLevel.JUNIOR, QuizLevel.SENIOR))
.build();
final Quiz quiz2 = Quiz.builder()
.title("quiz2")
.quizCategory(QuizCategory.JAVA)
.quizLevel(Arrays.asList(QuizLevel.NEW, QuizLevel.JUNIOR, QuizLevel.SENIOR))
.build();
final Quiz quiz3 = Quiz.builder()
.title("quiz3")
.quizCategory(QuizCategory.DATABASE)
.quizLevel(Arrays.asList(QuizLevel.NEW, QuizLevel.JUNIOR, QuizLevel.SENIOR))
.build();
final Quiz quiz4 = Quiz.builder()
.title("quiz4")
.quizCategory(QuizCategory.JAVA)
.quizLevel(Arrays.asList(QuizLevel.JUNIOR, QuizLevel.SENIOR))
.build();
quizRepository.save(quiz1);
quizRepository.save(quiz2);
quizRepository.save(quiz3);
quizRepository.save(quiz4);
// when
final Long result1 = quizRepository.countByQuizCategory(QuizCategory.JAVA);
final Long result2 = quizRepository.countByQuizCategory(QuizCategory.DATABASE);
// then
assertThat(result1).isEqualTo(3);
assertThat(result2).isEqualTo(1);
}
@Test
public void insertQuiz() {
// given

View File

@@ -1,10 +1,14 @@
package com.mangkyu.employment.interview.app.quiz.service;
import com.mangkyu.employment.interview.app.quiz.dto.AddQuizRequest;
import com.mangkyu.employment.interview.app.quiz.dto.QuizCategoryResponse;
import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.repository.QuizRepository;
import com.mangkyu.employment.interview.app.solvedquiz.entity.SolvedQuiz;
import com.mangkyu.employment.interview.app.solvedquiz.repository.SolvedQuizRepository;
import com.mangkyu.employment.interview.enums.common.EnumMapperKey;
import com.mangkyu.employment.interview.enums.common.EnumMapperValue;
import com.mangkyu.employment.interview.enums.factory.EnumMapperFactory;
import com.mangkyu.employment.interview.enums.value.QuizCategory;
import com.mangkyu.employment.interview.enums.value.QuizLevel;
import org.junit.jupiter.api.BeforeEach;
@@ -35,6 +39,8 @@ class QuizServiceTest {
private QuizRepository quizRepository;
@Mock
private SolvedQuizRepository solvedQuizRepository;
@Mock
private EnumMapperFactory enumMapperFactory;
@Spy
private ModelMapper modelMapper;
@@ -140,6 +146,35 @@ class QuizServiceTest {
assertThat(result.size()).isEqualTo(quizSize);
}
@Test
public void getQuizCategoryResponseList() {
// given
final long count = 15;
final QuizCategory quizCategory = QuizCategory.JAVA;
final List<Quiz> unsolvedQuizList = new ArrayList<>();
unsolvedQuizList.add(quiz(1L));
unsolvedQuizList.add(quiz(2L));
unsolvedQuizList.add(quiz(3L));
unsolvedQuizList.add(quiz(4L));
final EnumMapperValue enumMapperValue = EnumMapperValue.builder()
.code(quizCategory.name())
.title(quizCategory.getTitle())
.desc(quizCategory.getDesc())
.build();
doReturn(Collections.singletonList(enumMapperValue)).when(enumMapperFactory).get(EnumMapperKey.QUIZ_CATEGORY);
doReturn(count).when(quizRepository).countByQuizCategory(quizCategory);
// when
final List<QuizCategoryResponse> result = quizService.getQuizCategoryList();
// then
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(0).getCount()).isEqualTo(count);
}
private List<SolvedQuiz> solvedQuizList() {
return Arrays.asList(
solvedQuiz(1L),