Skip to content
Open
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2dec599
init commit
Curry4182 Jul 31, 2023
ecd61ec
init commit
Curry4182 Jul 31, 2023
a821939
feat: BaseEntity 및 JpaAuditingConfiguration 설정 파일 추가
Curry4182 Jul 31, 2023
75773a1
feat: ApiResponse 공통 응답 모델 추가
Curry4182 Jul 31, 2023
eff50c3
feat: user 관련 api 기능 추가
Curry4182 Jul 31, 2023
6d92014
feat: post 관련 api 기능 추가
Curry4182 Jul 31, 2023
a157d6f
test: user 테스트 기능 추가
Curry4182 Jul 31, 2023
767a062
test: post 테스트 기능 추가
Curry4182 Jul 31, 2023
e0ffc36
docs: rest docs api 결과 docs 추가
Curry4182 Jul 31, 2023
e684a26
docs: post.adoc 내용 수정
Curry4182 Jul 31, 2023
0db39ee
refactor: cursor방식으로 post를 반환할 때 client에 필요한 정보만 넘길 수 있도록 수정
Curry4182 Aug 5, 2023
f74b8d9
refactor: AllargsConstructor를 사용하지 않도록 수정, 클래스 이름 접미사DTO를 Dto로 모두 수정
Curry4182 Aug 5, 2023
c7107c4
refactor: 사용하지 않는 setter는 삭제, setter의 이름을 set 대신 의도를 파악할 수 있는 이름으로 수정
Curry4182 Aug 5, 2023
a9824bc
refactor: 공통적으로 사용하는 부분은 @BeforeAll이 붙어있는 setUP메서드에서 실행될 수 있도록 수정
Curry4182 Aug 5, 2023
aac52b4
refactor: 클래스의 객체에 직접 접근하지 않고 메서드를 통해 속성을 변경할 수 있도록 수정
Curry4182 Aug 7, 2023
3f95c3c
feat: dto와 entity에 유효성 검사 기능 추가, global exception 처리 기능 추가
Curry4182 Aug 7, 2023
54c57af
refactor: post에 update 메서드 추가, setter 메서드 private로 접근 외부에서 안되게 수정
Curry4182 Aug 7, 2023
abdc8c8
refactor: 단순 조회일 경우 Transactional을 readonly로 변경
Curry4182 Aug 7, 2023
e279941
refactor: Lob 어노테이션 대신 Text를 사용하도록 수정
Curry4182 Aug 7, 2023
5171145
refactor: 전체적으로 ApiResponse를 응답하도록 수정
Curry4182 Aug 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package com.programmers.heheboard.domain.post;

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.http.MediaType;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import com.fasterxml.jackson.databind.ObjectMapper;

@WebMvcTest(PostController.class)
@AutoConfigureRestDocs(uriScheme = "https")
class PostTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private PostService postService;

@Autowired
private ObjectMapper objectMapper;

@Test
void create() throws Exception {
// given
PostResponseDTO responseDTO = PostResponseDTO.builder()
.title("title")
.content("content")
.createdAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.modifiedAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.build();

when(postService.createPost(any(CreatePostRequestDto.class))).thenReturn(responseDTO);

// when
CreatePostRequestDto requestDto = new CreatePostRequestDto("title", "content", 1L);

ResultActions result = this.mockMvc.perform(
post("/posts")
.contentType((MediaType.APPLICATION_JSON))
.content(objectMapper.writeValueAsString(requestDto))
);

// then
result.andExpect(status().isOk())
.andDo(print())
.andDo(
document("post-save",
requestFields(
fieldWithPath("userId").type(JsonFieldType.NUMBER).description("User Id"),
fieldWithPath("title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("content").type(JsonFieldType.STRING).description("내용")
),
responseFields(
fieldWithPath("statusCode").type(JsonFieldType.NUMBER).description("상태코드"),
fieldWithPath("data.title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("data.content").type(JsonFieldType.STRING).description("내용"),
fieldWithPath("data.createdAt").type(JsonFieldType.STRING).description("생성일"),
fieldWithPath("data.modifiedAt").type(JsonFieldType.STRING).description("수정일")
)
)
);
}

@Test
void findSinglePost() throws Exception {
// given
PostResponseDTO responseDTO = PostResponseDTO.builder()
.title("title")
.content("content")
.createdAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.modifiedAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.build();

Long postId = 1L;

when(postService.findPost(postId)).thenReturn(responseDTO);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostId 를 직접 지정해서 사용하는 것보다 anyLong을 사용해보는 건 어떤가요??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고민 해보았는데 입력한 postId를 컨트롤러에서 동일하게 찾는지 테스트 해보기 위해서 postId를 계속 사용할려고 합니다!


// when
ResultActions result = this.mockMvc.perform(
get("/posts/%,d".formatted(postId))
);

// then
result.andExpect(status().isOk())
.andDo(print())
.andDo(document("post-find",
responseFields(
fieldWithPath("statusCode").type(JsonFieldType.NUMBER).description("상태코드"),
fieldWithPath("data.title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("data.content").type(JsonFieldType.STRING).description("내용"),
fieldWithPath("data.createdAt").type(JsonFieldType.STRING).description("생성일"),
fieldWithPath("data.modifiedAt").type(JsonFieldType.STRING).description("수정일")
)
)
);
}

@Test
void getPosts() throws Exception {
// given
List<PostResponseDTO> postList = Arrays.asList(
PostResponseDTO.builder()
.title("title3")
.content("content3")
.createdAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.modifiedAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.build(),

PostResponseDTO.builder()
.title("title4")
.content("content4")
.createdAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.modifiedAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.build()
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반복해서 사용하는 내용들이라면 beforeEach를 만들어서 넣고 사용해도 좋을 것 같아요~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostResponseDTO를 공통적으로 생성해서 그 부분을 setUP메서드에 넣었습니다~! a9824bc


Slice<PostResponseDTO> responseSlice = new SliceImpl<>(postList);

int page = 1;
int size = 2;

when(postService.getPosts(page, size)).thenReturn(responseSlice);

// when
ResultActions result = this.mockMvc.perform(
get("/posts")
.param("page", String.valueOf(page))
.param("size", String.valueOf(size))
);

// then
result.andExpect(status().isOk())
.andDo(print())
.andDo(document("post-get",
responseFields(
fieldWithPath("statusCode").type(JsonFieldType.NUMBER).description("상태코드"),
fieldWithPath("data.content").description("List of Posts"),
fieldWithPath("data.content[].title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("data.content[].content").type(JsonFieldType.STRING).description("내용"),
fieldWithPath("data.content[].createdAt").type(JsonFieldType.STRING).description("생성일"),
fieldWithPath("data.content[].modifiedAt").type(JsonFieldType.STRING).description("수정일"),

fieldWithPath("data.pageable").type(JsonFieldType.STRING).description("pageable"),

fieldWithPath("data.size").type(JsonFieldType.NUMBER).description("size"),
fieldWithPath("data.number").type(JsonFieldType.NUMBER).description("number"),

fieldWithPath("data.sort.unsorted").type(JsonFieldType.BOOLEAN).description("unsorted"),
fieldWithPath("data.sort.empty").type(JsonFieldType.BOOLEAN).description("empty"),
fieldWithPath("data.sort.sorted").type(JsonFieldType.BOOLEAN).description("sorted"),

fieldWithPath("data.first").type(JsonFieldType.BOOLEAN).description("first"),
fieldWithPath("data.last").type(JsonFieldType.BOOLEAN).description("last"),
fieldWithPath("data.numberOfElements").type(JsonFieldType.NUMBER).description("numberOfElements"),
fieldWithPath("data.empty").type(JsonFieldType.BOOLEAN).description("empty")
)
)
);
}

@Test
void update() throws Exception {
Long postId = 1L;

PostResponseDTO responseDTO = PostResponseDTO.builder()
.title("updated title")
.content("updated content")
.createdAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.modifiedAt(LocalDateTime.of(2000, 1, 1, 1, 1))
.build();

when(postService.updatePost(eq(1L), any(UpdatePostRequestDto.class))).thenReturn(responseDTO);

UpdatePostRequestDto updatePostRequestDto = new UpdatePostRequestDto("updated content", "updated content");

// when
ResultActions result = this.mockMvc.perform(
put("/posts/%,d".formatted(postId))
.contentType((MediaType.APPLICATION_JSON))
.content(objectMapper.writeValueAsString(updatePostRequestDto))
);

// then
result.andExpect(status().isOk())
.andDo(print())
.andDo(
document("post-update",
requestFields(
fieldWithPath("title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("content").type(JsonFieldType.STRING).description("내용")
),
responseFields(
fieldWithPath("statusCode").type(JsonFieldType.NUMBER).description("상태코드"),
fieldWithPath("data.title").type(JsonFieldType.STRING).description("제목"),
fieldWithPath("data.content").type(JsonFieldType.STRING).description("내용"),
fieldWithPath("data.createdAt").type(JsonFieldType.STRING).description("생성일"),
fieldWithPath("data.modifiedAt").type(JsonFieldType.STRING).description("수정일")
)
)
);
}
}