Skip to content

Commit

Permalink
test(#19): 자주묻는질문 ControllerTest
Browse files Browse the repository at this point in the history
- 자주묻는질문 컨틀롤러 테스트를 작성했어요.
  • Loading branch information
cabbage16 committed Nov 23, 2024
1 parent 8a66d76 commit ad66d70
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.bamdoliro.sinabro.domain.question.domain.Question;
import com.bamdoliro.sinabro.domain.question.service.QuestionFacade;
import com.bamdoliro.sinabro.infrastructure.persistence.question.QuestionRepository;
import com.bamdoliro.sinabro.presentation.question.dto.request.QuestionRequest;
import com.bamdoliro.sinabro.shared.annotation.UseCase;
import jakarta.transaction.Transactional;
Expand All @@ -12,7 +11,6 @@
@UseCase
public class UpdateQuestionUseCase {

private final QuestionRepository questionRepository;
private final QuestionFacade questionFacade;

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
package com.bamdoliro.sinabro.presentation.question;

import com.bamdoliro.sinabro.domain.question.exception.QuestionNotFoundException;
import com.bamdoliro.sinabro.domain.user.domain.User;
import com.bamdoliro.sinabro.presentation.diary.dto.request.DiaryRequest;
import com.bamdoliro.sinabro.presentation.question.dto.request.QuestionRequest;
import com.bamdoliro.sinabro.presentation.question.dto.response.ListQuestionResponse;
import com.bamdoliro.sinabro.presentation.question.dto.response.QuestionResponse;
import com.bamdoliro.sinabro.shared.fixture.*;
import com.bamdoliro.sinabro.shared.util.RestDocsTestSupport;
import org.junit.jupiter.api.Test;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.restdocs.payload.JsonFieldType;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
import static org.springframework.restdocs.request.RequestDocumentation.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class QuestionControllerTest extends RestDocsTestSupport {

@Test
void 자주묻는질문을_생성한다() throws Exception {
User user = UserFixture.createAdmin();
QuestionRequest request = QuestionFixture.createQuestionRequest();

given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true);
given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user);
given(createQuestionUseCase.execute(any(QuestionRequest.class))).willReturn(SharedFixture.createIdResponse());

mockMvc.perform(post("/questions")
.header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(request))
)

.andExpect(status().isCreated())

.andDo(restDocs.document(
requestHeaders(
headerWithName(HttpHeaders.AUTHORIZATION)
.description("Bearer Token")
),
requestFields(
fieldWithPath("title")
.type(JsonFieldType.STRING)
.description("제목(최대 64자)"),
fieldWithPath("content")
.type(JsonFieldType.STRING)
.description("내용(최대 1024자")
)
));

verify(createQuestionUseCase, times(1)).execute(any(QuestionRequest.class));
}

@Test
void 자주묻는질문을_전체_조회한다() throws Exception {
List<ListQuestionResponse> responseList = List.of(
QuestionFixture.createListQuestionResponse(),
QuestionFixture.createListQuestionResponse(),
QuestionFixture.createListQuestionResponse()
);

given(getAllQuestionUseCase.execute()).willReturn(responseList);

mockMvc.perform(get("/questions")
.contentType(MediaType.APPLICATION_JSON)
)

.andExpect(status().isOk())

.andDo(restDocs.document());

verify(getAllQuestionUseCase, times(1)).execute();
}

@Test
void 자주묻는질문을_조회한다() throws Exception {
Long id = 1L;
QuestionResponse response = QuestionFixture.createQuestionResponse();

given(getQuestionUseCase.execute(anyLong())).willReturn(response);

mockMvc.perform(get("/questions/{question-id}", id)
.contentType(MediaType.APPLICATION_JSON)
)

.andExpect(status().isOk())

.andDo(restDocs.document(
pathParameters(
parameterWithName("question-id")
.description("조회할 자주묻는질문의 id")
)
));

verify(getQuestionUseCase, times(1)).execute(anyLong());
}

@Test
void 자주묻는질문을_조회할_때_자주묻는질문이_없으면_예외가_발생한다() throws Exception {
Long id = 1L;
given(getQuestionUseCase.execute(anyLong())).willThrow(new QuestionNotFoundException());

mockMvc.perform(get("/questions/{question-id}", id)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
)

.andExpect(status().isNotFound())

.andDo(restDocs.document());

verify(getQuestionUseCase, times(1)).execute(anyLong());
}

@Test
void 자주묻는질문을_수정한다() throws Exception {
Long id = 1L;
User user = UserFixture.createAdmin();
QuestionRequest request = QuestionFixture.createQuestionRequest();

given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true);
given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user);
willDoNothing().given(updateQuestionUseCase).execute(anyLong(), any(QuestionRequest.class));

mockMvc.perform(put("/questions/{question-id}", id)
.header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(request))
)

.andExpect(status().isNoContent())

.andDo(restDocs.document(
requestHeaders(
headerWithName(HttpHeaders.AUTHORIZATION)
.description("Bearer Token")
),
pathParameters(
parameterWithName("question-id")
.description("수정할 자주묻는질문 id")
),
requestFields(
fieldWithPath("title")
.type(JsonFieldType.STRING)
.description("64글자 이내의 제목"),
fieldWithPath("content")
.type(JsonFieldType.STRING)
.description("1024글자 이내의 내용")
)
));

verify(updateQuestionUseCase, times(1)).execute(anyLong(), any(QuestionRequest.class));
}

@Test
void 자주묻는질문을_수정할_때_자주묻는질문이_없으면_에러가_발생한다() throws Exception {
Long id = 1L;
User user = UserFixture.createAdmin();
QuestionRequest request = QuestionFixture.createQuestionRequest();

given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true);
given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user);
willThrow(new QuestionNotFoundException()).given(updateQuestionUseCase).execute(anyLong(), any(QuestionRequest.class));

mockMvc.perform(put("/questions/{question-id}", id)
.header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(request)))

.andExpect(status().isNotFound())

.andDo(restDocs.document());
}

@Test
void 자주묻는질문을_삭제한다() throws Exception {
Long id = 1L;
User user = UserFixture.createAdmin();

given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true);
given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user);
willDoNothing().given(deleteQuestionUseCase).execute(id);

mockMvc.perform(delete("/questions/{question-id}", id)
.header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader())
.accept(MediaType.APPLICATION_JSON)
)

.andExpect(status().isNoContent())

.andDo(restDocs.document(
requestHeaders(
headerWithName(HttpHeaders.AUTHORIZATION)
.description("Bearer token")
),
pathParameters(
parameterWithName("question-id")
.description("삭제할 자주묻는질문 id")
)
));

verify(deleteQuestionUseCase, times(1)).execute(id);
}

@Test
void 자주묻는질문을_삭제할_때_자주묻는질문이_없으면_에러가_발생한다() throws Exception {
Long id = 1L;
User user = UserFixture.createAdmin();

given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true);
given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user);
willThrow(new QuestionNotFoundException()).given(deleteQuestionUseCase).execute(anyLong());

mockMvc.perform(delete("/questions/{question-id}", id)
.header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader())
.accept(MediaType.APPLICATION_JSON)
)

.andExpect(status().isNotFound())

.andDo(restDocs.document());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.bamdoliro.sinabro.shared.fixture;

import com.bamdoliro.sinabro.presentation.question.dto.request.QuestionRequest;
import com.bamdoliro.sinabro.presentation.question.dto.response.ListQuestionResponse;
import com.bamdoliro.sinabro.presentation.question.dto.response.QuestionResponse;

import java.time.LocalDateTime;

public class QuestionFixture {

public static QuestionRequest createQuestionRequest() {
return new QuestionRequest(
"캐릭터 편지 몇일에 한번씩 발송되나요?",
"캐릭터들의 편지는 보통 1일~3일 내에 1통 발송됩니다."
);
}

public static ListQuestionResponse createListQuestionResponse() {
return new ListQuestionResponse(
1L,
"캐릭터 편지 몇일에 한번씩 발송되나요?",
"캐릭터들의 편지는 보통 1일~3일 내에 1통 발송됩니다.",
LocalDateTime.now()
);
}

public static QuestionResponse createQuestionResponse() {
return new QuestionResponse(
1L,
"캐릭터 편지 몇일에 한번씩 발송되나요?",
"캐릭터들의 편지는 보통 1일~3일 내에 1통 발송됩니다.",
LocalDateTime.now(),
LocalDateTime.now()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ public class UserFixture {
public static User createUser() {
return new User("bamdoliro@gmail.com", "김밤돌", Authority.USER);
}

public static User createAdmin() {
return new User("bamdoliro@gmail.com", "어다민", Authority.ADMIN);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.bamdoliro.sinabro.application.auth.*;
import com.bamdoliro.sinabro.application.diary.*;
import com.bamdoliro.sinabro.application.question.*;
import com.bamdoliro.sinabro.domain.auth.service.TokenService;
import com.bamdoliro.sinabro.presentation.auth.AuthController;
import com.bamdoliro.sinabro.presentation.diary.DiaryController;
Expand All @@ -13,6 +14,7 @@
import com.bamdoliro.sinabro.presentation.character.CharacterController;
import com.bamdoliro.sinabro.presentation.fcm.token.FCMTokenController;
import com.bamdoliro.sinabro.presentation.notification.NotificationController;
import com.bamdoliro.sinabro.presentation.question.QuestionController;
import com.bamdoliro.sinabro.presentation.user.UserController;
import com.bamdoliro.sinabro.shared.auth.AuthenticationArgumentResolver;
import com.bamdoliro.sinabro.shared.auth.AuthenticationExtractor;
Expand All @@ -21,6 +23,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Disabled;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
Expand All @@ -34,6 +37,7 @@
NotificationController.class,
FCMTokenController.class,
CharacterController.class,
QuestionController.class,
SharedController.class
})
public abstract class ControllerTest {
Expand Down Expand Up @@ -82,7 +86,6 @@ public abstract class ControllerTest {
@MockBean
protected DeleteDiaryUseCase deleteDiaryUseCase;

// Character
@MockBean
protected SendNotificationUseCase sendNotificationUseCase;

Expand All @@ -98,6 +101,22 @@ public abstract class ControllerTest {
@MockBean
protected SelectCharacterUseCase selectCharacterUseCase;

// Question
@MockBean
protected CreateQuestionUseCase createQuestionUseCase;

@MockBean
protected GetAllQuestionUseCase getAllQuestionUseCase;

@MockBean
protected GetQuestionUseCase getQuestionUseCase;

@MockBean
protected UpdateQuestionUseCase updateQuestionUseCase;

@MockBean
protected DeleteQuestionUseCase deleteQuestionUseCase;

// Service
@MockBean
protected TokenService tokenService;
Expand Down

0 comments on commit ad66d70

Please sign in to comment.