Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test] QuestionController.createQuestion 테스트 코드 작성 #148

Merged
merged 7 commits into from
Feb 13, 2024
2 changes: 0 additions & 2 deletions src/main/java/qp/official/qp/QpBackendApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import javax.annotation.PostConstruct;
import java.util.TimeZone;

@SpringBootApplication
@EnableJpaAuditing
public class QpBackendApplication {

static {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package qp.official.qp.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration
@EnableJpaAuditing
public class JpaEnversConfiguration {
}
21 changes: 21 additions & 0 deletions src/main/java/qp/official/qp/config/ObjectMapperConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package qp.official.qp.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;

@Configuration
public class ObjectMapperConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.ifPresent(converter -> ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(UTF_8));
}
}
1 change: 1 addition & 0 deletions src/main/java/qp/official/qp/domain/Question.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import qp.official.qp.web.dto.QuestionRequestDTO;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
public class QuestionController {
private final QuestionCommandService questionCommandService;
private final QuestionQueryService questionQueryService;
private final TokenService tokenService;

// 질문 작성
@PostMapping
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package qp.official.qp.web.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import qp.official.qp.apiPayload.ApiResponse;
import qp.official.qp.domain.Hashtag;
import qp.official.qp.domain.Question;
import qp.official.qp.domain.User;
import qp.official.qp.repository.HashtagRepository;
import qp.official.qp.repository.UserRepository;
import qp.official.qp.service.QuestionService.QuestionCommandService;
import qp.official.qp.service.QuestionService.QuestionQueryService;
import qp.official.qp.service.TokenService.TokenService;
import qp.official.qp.web.dto.QuestionRequestDTO;
import qp.official.qp.web.dto.QuestionResponseDTO;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

// WebMvcTest를 사용하여 QuestionController를 테스트
// WebMvcTest는 Controller가 의존하는 Bean들만 로드하여 테스트
@WebMvcTest(QuestionController.class)
class QuestionControllerTest {

@MockBean
private QuestionCommandService questionCommandService;
@MockBean
private QuestionQueryService questionQueryService;

// ExistHashTag 어노테이션에서 사용하는 HashtagRepository
@MockBean
private HashtagRepository hashtagRepository;

// ExistUser 어노테이션에서 사용하는 UserRepository
@MockBean
private UserRepository userRepository;

@MockBean
private TokenService tokenService;

// MockMvc를 사용하여 API를 테스트
private final MockMvc mockMvc;

// ObjectMapper를 사용하여 객체를 JSON으로 변환 또는 JSON을 객체로 변환
private final ObjectMapper objectMapper;

@Autowired
public QuestionControllerTest(
MockMvc mockMvc,
ObjectMapper objectMapper
) {
this.mockMvc = mockMvc;
this.objectMapper = objectMapper;
}

@Test
void createQuestion() throws Exception {
// given
String testTitle = "new title";
String testContent = "new content";

Long userId = 1L;
Long questionId = 1L;
LocalDateTime createdAt = LocalDateTime.now();

// Request 객체 생성
QuestionRequestDTO.CreateDTO questionRequest = QuestionRequestDTO.CreateDTO.builder()
.userId(userId)
.title(testTitle)
.content(testContent)
.hashtag(new ArrayList<>())
.build();


// Expect Response 객체 생성
Question questionResponse = Question.builder()
.questionId(questionId)
.title(testTitle)
.content(testContent)
.answers(new ArrayList<>())
.build();

// Setter 없이 ReflectionTestUtils를 사용하여 필드값을 설정
ReflectionTestUtils.setField(questionResponse, "createdAt", createdAt);

// questionCommandService 에서 createQuestion 메소드가 호출될 때 questionResponse를 반환하도록 설정
when(questionCommandService.createQuestion(any(QuestionRequestDTO.CreateDTO.class))).thenReturn(questionResponse);
// ExistUser 어노테이션을 통과하기 위해 userRepository 에서 findById 메소드가 호출될 때 아무 Optional.of(User.builder().build())를 반환하도록 설정
when(userRepository.findById(any(Long.class))).thenReturn(Optional.of(User.builder().build()));
// ExistHashTag 어노테이션을 통과하기 위해 hashtagRepository 에서 findById 메소드가 호출될 때 아무 Optional.of(Hashtag.builder().build())를 반환하도록 설정
when(hashtagRepository.findById(any(Long.class))).thenReturn(Optional.of(Hashtag.builder().build()));

// when
// Request 객체를 JSON으로(request body로) 변환
String body = objectMapper.writeValueAsString(questionRequest);
// API 호출
ResultActions action = mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType("application/json")
.content(body));

// then
// API 호출 결과가 200 OK인지 확인
action.andExpect(status().isOk());

// API 호출 결과를 ApiResponse 객체로 변환
ApiResponse<QuestionResponseDTO.CreateResultDTO> response = objectMapper.readValue(
action.andReturn().getResponse().getContentAsString(),
new TypeReference<>() {
}
);

// questionId 확인
assertEquals(questionId, response.getResult().getQuestionId());

// createAt 확인
assertEquals(createdAt, response.getResult().getCreatedAt());
}
}
Loading