Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- Kernighan의 C언어 프로그래밍
- 알파회계
- network configuration
- 목록처리
- 자료구조와 함께 배우는 알고리즘 입문
- baeldung
- 리눅스
- 서버설정
- 데비안
- 티스토리 쿠키 삭제
- 페이징
- /etc/network/interfaces
- 네트워크 설정
- iterator
- resttemplate
- 스프링 시큐리티
- GIT
- 친절한SQL튜닝
- 스프링부트핵심가이드
- d
- 처음 만나는 AI수학 with Python
- 자료구조와함께배우는알고리즘입문
- 처음 만나는 AI 수학 with Python
- 코드로배우는스프링부트웹프로젝트
- 자바편
- ㅒ
- 코드로배우는스프링웹프로젝트
- 이터레이터
- 선형대수
- 구멍가게코딩단
Archives
- Today
- Total
bright jazz music
blog10: 게시글 수정 2 (오류수정, 보충) 본문
//PostService.java
//PostEdit에서 검증하지 않는다면 아래와 같은 로직이 들어가야 한다.
@Transactional
public void edit(Long id, PostEdit postEdit){
Post post = postRepository.findById(id).orElseThrow(PostNotFound::new);
post.edit(
postEdit.getTitle() != null ? postEdit.getTitle() : post.getTitle();
postEdit.getContent() != null ? postEdit.getContent() : post.getContent());
}
이게 귀찮아서 PostEditor를 만들어 준 것이다.
2. PostService.java에서
값을 넣어줬을 때는 내부의 빌더 클래스에 값이 들어가 진 것이지, PostEditor의 값이 들어간 것이 아니다.
//PostService.java
package com.endofma.blog.service;
import com.endofma.blog.domain.Post;
import com.endofma.blog.domain.PostEditor;
import com.endofma.blog.repository.PostRepository;
import com.endofma.blog.request.PostCreate;
import com.endofma.blog.request.PostEdit;
import com.endofma.blog.request.PostSearch;
import com.endofma.blog.response.PostResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Slf4j
@Service
//@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository){
this.postRepository = postRepository;
}
public void write(PostCreate postCreate) {
//PostCreate 일반 클래스 ==> Post 엔티티
Post post = Post.builder()
.title(postCreate.getTitle())
.content(postCreate.getContent())
.build();
postRepository.save(post);
}
//단건 조회
public PostResponse get(Long id) {
Post post = postRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 글입니다.")); //있으면 post반환 없으면 에러 반환
//응답 클래스를 분리
return PostResponse.builder()
.id(post.getId())
.title(post.getTitle())
.content(post.getContent())
.build();
}
// public List<Post> getList() {
// return postRepository.findAll();
// }
// public List<PostResponse> getList(Pageable pageable){
public List<PostResponse> getList(PostSearch postSearch){
// return postRepository.findAll(pageable).stream() //pageable
return postRepository.getList(postSearch).stream() //QueryDsl사용
.map(PostResponse::new)
.collect(Collectors.toList());
}
//게시글 수정
@Transactional //알아서 커밋
public void edit(Long id, PostEdit postEdit){
Post post = postRepository.findById(id)
.orElseThrow(()-> new IllegalArgumentException("존재하지 않는 글입니다."));
// post.setTitle(postEdit.getTitle());
// post.setContent(postEdit.getContent());
// post.change(postEdit.getTitle(), postEdit.getContent());
// postRepository.save(post); 사실상 적어주지 않아도 된다. 대신 @Transactional을 사용
PostEditor.PostEditorBuilder editorBuilder = post.toEditor();
PostEditor postEditor = editorBuilder
.title(postEdit.getTitle())
.content(postEdit.getContent())
.build();
post.edit(postEditor);
}
}
//PostController.java
package com.endofma.blog.controller;
import com.endofma.blog.domain.Post;
import com.endofma.blog.request.PostCreate;
import com.endofma.blog.request.PostEdit;
import com.endofma.blog.request.PostSearch;
import com.endofma.blog.response.PostResponse;
import com.endofma.blog.service.PostService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequiredArgsConstructor
public class PostController {
private final PostService postService;
@PostMapping("/posts")
public void post(@RequestBody @Valid PostCreate request) {
postService.write(request);
// return Map.of();
}
//단건 조회
@GetMapping("/posts/{postId}")
public PostResponse get(@PathVariable Long postId){
PostResponse response = postService.get(postId);
return response;
}
//여러 글 조회(글 목록 가져오기)
// /posts
@GetMapping("/posts")
//글이 너무 많은 경우 비용이 너무 많이 든다.
//DB가 뻗을 수 있음.
//DB -> 애플리케이션 서버로 전달하는 시간, 트래픽 비용이 많이 발생할 수 있다.
//따라서 페이지 설정
// 원래는 int로 받았음
// public List<PostResponse> getList(@RequestParam int page){
// 그러나 사용의 용이성을 위해 pageable을 사용함
// public List<PostResponse> getList(@PageableDefault Pageable pageable){ //1로 넘겨도 0으로 보정해서 넣어줌.
//근데 PageableDefault의 기본 size가 10이라 yml에서 설정해도 먹히지 않는다.
//이 떄는 어노테이션을 그대로 유지하면서 size를 파라미터로 넣어주는 방법이 있다.
//public List<PostResponse> getList(@PageableDefault(size=10) Pageable pageable){
//또는 어노테이션을 빼고 application.yml에서 default-page-size를 설정하여 해결할 수 수있다.
//전에는 Pageable을 사용했으나 여러 요구사항을 수용 할 수 있는 클래스를 사용하기 위해
//postSearch 클래스 사용
public List<PostResponse> getList(@ModelAttribute PostSearch postSearch){//따로 만든 요청클래스 사용하려고 함
// public List<PostResponse> getList(Pageable pageable){
return postService.getList(postSearch);
}
@PatchMapping("/posts/{postId}")
public void edit(@PathVariable Long postId, @RequestBody @Valid PostEdit request){
postService.edit(postId, request);
}
}
//PostEditor.java
package com.endofma.blog.domain;
import lombok.Builder;
import lombok.Getter;
@Getter
public class PostEditor {
//수정해야할 필드만 좁혀서 수정하기 때문에 이 값들만 수정 가능하다는 것을 직관적으로 알 수 있다.
private String title = null;
private String content = null;
public PostEditor(String title, String content) {
this.title = title;
this.content = content;
//여기서 if문으로 사용해 null을 필터링 하는 것은 의미가 없다.
//빌더 클래스에 값이 들어간 것이기 때문이다.
}
public static PostEditor.PostEditorBuilder builder(){
return new PostEditorBuilder();
}
public static class PostEditorBuilder{
private String title;
private String content;
PostEditorBuilder(){
}
public PostEditor.PostEditorBuilder title(final String title){
if (title != null) {
this.title = title;
}
return this;
}
public PostEditor.PostEditorBuilder content(final String content){
if(content != null) {
this.content = content;
}
return this;
}
public PostEditor build(){
return new PostEditor(this.title, this.content);
}
@Override
public String toString() {
return "PostEditorBuilder{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
}
//PostControllerTest.java
package com.endofma.blog.controller;
import com.endofma.blog.domain.Post;
import com.endofma.blog.repository.PostRepository;
import com.endofma.blog.request.PostCreate;
import com.endofma.blog.request.PostEdit;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; //이게 맞음
//import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath; 원래 이걸로 했음.
//@WebMvcTest //간단한 웹테스트만 가능. 우린 스프링 전반에 걸쳐 여러 가지를 만들었기 때문에 @SpringBootTest가 필요
@AutoConfigureMockMvc //@WebMvcTest가 없어지면 기존 테스트가 안되므로 @WebMvcTest를 구성하는 애노테이션을 떼내어 붙였다.
@SpringBootTest
class PostControllerTest {
@Autowired
private MockMvc mockMvc; ////Could not autowire. No beans of 'MockMvc' type found.
@Autowired
private PostRepository postRepository; //DB저장 테스트를 위해 주입
@BeforeEach
void clean() {
postRepository.deleteAll();
}
@Test
@DisplayName("/posts 요청시 hello world를 출력한다")
void test() throws Exception {
//given
// PostCreate request = new PostCreate("제목입니다.", "내용입니다.");
PostCreate request = PostCreate.builder()
.title("제목입니다.")
.content("내용입니다.")
.build();
//jackson을 사용하여 객체를 Json 형태로 바꿔준다.(json을 처리해 줌)
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(request);
// @Autowired private ObjectMapper objectMapper; 이렇게 주입해서도 쓸 수 있다.
System.out.println(json);
//expected
//기본적으로 Content-Type을 application/json으로 보냄. 예전에는 application/x-www-form-urlencoded를 썼다.
mockMvc.perform(post("/posts")
.contentType(APPLICATION_JSON) //기본값이라 주석처리
// .content("{\"title\": \"제목입니다.\", \"content\": \"내용입니다.\"}") //json 형태로 값 넣어주기
//.content에는 byte나 String만 들어가진다. 따라서 jackson으로 Json변환처리를 하지 않은 request를 넣을 수는 없다.
.content(json) //jackson을 사용하여 json이 된 객체. 클래스에 게터가 존재해야 한다.
)
.andExpect(status().isOk()) //http response 가 200인지
.andExpect(content().string("")) // 내용이 hello world인지
.andDo(print()); //요청에 대한 전반적인 요약을 출력해준다.
}
@Test
@DisplayName("/posts 요청시 title 값은 필수다")
void test2() throws Exception {
//given
PostCreate request = PostCreate.builder()
//.title("제목입니다.")
.content("내용입니다.")
.build();
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(request);
//expected
mockMvc.perform(post("/posts")
.contentType(APPLICATION_JSON)
.content(json)
)
.andExpect(status().isBadRequest()) //.OK()
.andExpect(jsonPath("$.code").value("400")) //json 검증
.andExpect(jsonPath("$.message").value("잘못된 요청입니다!"))
// .andExpect(jsonPath("$.validation.title").value("타이틀을 입력하세요!"))
.andDo(print());
}
@Test
@DisplayName("/posts 요청시 DB에 값이 저장된다.")
void test3() throws Exception {
//given
PostCreate request = PostCreate.builder()
.title("제목입니다.")
.content("내용입니다.")
.build();
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(request);
//when
mockMvc.perform(post("/posts")
.contentType(APPLICATION_JSON)
.content(json)
)
.andExpect(status().isOk())
.andDo(print());
//then
assertEquals(1L, postRepository.count()); //하나의 값이 있을 거라고 예상. 일치
//DB에 잘 들어갔는지 확인
Post post = postRepository.findAll().get(0); //가장 처음 데이터 가져옴
assertEquals("제목입니다.", post.getTitle());
assertEquals("내용입니다.", post.getContent());
}
@Test
@DisplayName("글 1개 조회")
void test4() throws Exception{
//given
Post post = Post.builder()
.title("123456789012345")
.content("bar")
.build();
System.out.println("post.getId!!1="+ post.getId()); //==null
postRepository.save(post);
System.out.println("post.getId!!2="+ post.getId()); //==1
//expected
mockMvc.perform(get("/posts/{postId}", post.getId())
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(post.getId()))
.andExpect(jsonPath("$.title").value("1234567890"))
.andExpect(jsonPath("$.content").value("bar"))
.andDo(print());
}
@Test
@DisplayName("글 여러 개 조회")
void test5() throws Exception{
//given
List<Post> requestPost = IntStream.range(1, 20) //for (int =0; i<30; i++)
.mapToObj(i -> Post.builder()
.title("foo " + i)
.content("bar " + i)
.build()).collect(Collectors.toList());
postRepository.saveAll(requestPost);
//expected
// mockMvc.perform(get("/posts?page=1")
mockMvc.perform(get("/posts?page=1&size=10")
// mockMvc.perform(get("/posts?page=1&sort=id,desc&size=5")
//size를 매번 넣어주기 귀찮으면 application.yml에 가서 default-page-size를 설정해 준다.
//보통 현업에서는 10개보기 ,20개 보기 등의 옵션이 없으면 그냥 서버가 주는대로 받기 때문에
//size를 파라미터로 넘기는 경우가 많지는 않다.
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()", is(10)))
// .andExpect(jsonPath("$[0].id").value(30))
.andExpect(jsonPath("$[0].title").value("foo 19"))
.andExpect(jsonPath("$[0].content").value("bar 19"))
.andDo(print());
}
@Test
@DisplayName("페이지를 0으로 요청해도 첫 페이지를 가져온다.")
void test6() throws Exception{
//given
List<Post> requestPost = IntStream.range(1, 20) //for (int =0; i<30; i++)
.mapToObj(i -> Post.builder()
.title("foo " + i)
.content("bar " + i)
.build()).collect(Collectors.toList());
postRepository.saveAll(requestPost);
//expected
// mockMvc.perform(get("/posts?page=1")
mockMvc.perform(get("/posts?page=0&size=10")
// mockMvc.perform(get("/posts?page=1&sort=id,desc&size=5")
//size를 매번 넣어주기 귀찮으면 application.yml에 가서 default-page-size를 설정해 준다.
//보통 현업에서는 10개보기 ,20개 보기 등의 옵션이 없으면 그냥 서버가 주는대로 받기 때문에
//size를 파라미터로 넘기는 경우가 많지는 않다.
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()", is(10)))
// .andExpect(jsonPath("$[0].id").value(30))
.andExpect(jsonPath("$[0].title").value("foo 19"))
.andExpect(jsonPath("$[0].content").value("bar 19"))
.andDo(print());
}
@Test
@DisplayName("페이지를 0으로 요청해도 첫 페이지를 가져온다.")
void test7() throws Exception{
//given
ObjectMapper objectMapper = new ObjectMapper();
Post post = Post.builder()
.title("블로그 ")
.content("제이드빌 ")
.build();
postRepository.save(post);
PostEdit postEdit = PostEdit.builder()
.title("블로그 수정")
.content("부림동 ")
.build();
//expected
mockMvc.perform(patch("/posts/{postId}", post.getId())
.contentType(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(postEdit)))
.andExpect(status().isOk())
.andDo(print());
}
}
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava UP-TO-DATE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
Connected to the target VM, address: 'localhost:60596', transport: 'socket'
> Task :test
22:56:05.394 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
22:56:05.411 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
22:56:05.473 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.endofma.blog.controller.PostControllerTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
22:56:05.488 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.endofma.blog.controller.PostControllerTest], using SpringBootContextLoader
22:56:05.495 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.endofma.blog.controller.PostControllerTest]: class path resource [com/endofma/blog/controller/PostControllerTest-context.xml] does not exist
22:56:05.495 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.endofma.blog.controller.PostControllerTest]: class path resource [com/endofma/blog/controller/PostControllerTestContext.groovy] does not exist
22:56:05.496 [Test worker] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.endofma.blog.controller.PostControllerTest]: no resource found for suffixes {-context.xml, Context.groovy}.
22:56:05.497 [Test worker] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.endofma.blog.controller.PostControllerTest]: PostControllerTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
22:56:05.577 [Test worker] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.endofma.blog.controller.PostControllerTest]
22:56:05.678 [Test worker] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [D:\personal\blog\build\classes\java\main\com\endofma\blog\BlogApplication.class]
22:56:05.680 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.endofma.blog.BlogApplication for test class com.endofma.blog.controller.PostControllerTest
22:56:05.838 [Test worker] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [com.endofma.blog.controller.PostControllerTest]: using defaults.
22:56:05.838 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
22:56:05.861 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@2e27d72f, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@c0b41d6, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@4837595f, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@2bffa76d, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@3b718392, org.springframework.test.context.support.DirtiesContextTestExecutionListener@6d2260db, org.springframework.test.context.transaction.TransactionalTestExecutionListener@1f2d2181, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@49bf29c6, org.springframework.test.context.event.EventPublishingTestExecutionListener@7ee55e70, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@3fcdcf, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@7668d560, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@46292372, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@126be319, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@6c44052e, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@5c371e13]
22:56:05.865 [Test worker] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@5a6d5a8f testClass = PostControllerTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@4a67318f testClass = PostControllerTest, locations = '{}', classes = '{class com.endofma.blog.BlogApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@306851c7, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@4b3fa0b3, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@609640d5, [ImportsContextCustomizer@315ba14a key = [org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2b43529a, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@c260bdc, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@38be305c, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@495ee280], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null].
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.6)
2023-01-09 22:56:06.448 INFO 9144 --- [ Test worker] c.e.blog.controller.PostControllerTest : Starting PostControllerTest using Java 11.0.12 on DESKTOP-Q7HBM41 with PID 9144 (started by user in D:\personal\blog)
2023-01-09 22:56:06.451 INFO 9144 --- [ Test worker] c.e.blog.controller.PostControllerTest : No active profile set, falling back to 1 default profile: "default"
2023-01-09 22:56:07.514 INFO 9144 --- [ Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-01-09 22:56:07.608 INFO 9144 --- [ Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 79 ms. Found 1 JPA repository interfaces.
2023-01-09 22:56:08.516 INFO 9144 --- [ Test worker] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2023-01-09 22:56:08.857 INFO 9144 --- [ Test worker] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2023-01-09 22:56:08.973 INFO 9144 --- [ Test worker] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-01-09 22:56:09.060 INFO 9144 --- [ Test worker] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.14.Final
2023-01-09 22:56:09.437 INFO 9144 --- [ Test worker] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-01-09 22:56:09.645 INFO 9144 --- [ Test worker] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2023-01-09 22:56:10.641 INFO 9144 --- [ Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-01-09 22:56:10.652 INFO 9144 --- [ Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-01-09 22:56:11.725 WARN 9144 --- [ Test worker] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-01-09 22:56:12.318 INFO 9144 --- [ Test worker] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:blog'
2023-01-09 22:56:12.932 INFO 9144 --- [ Test worker] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
2023-01-09 22:56:12.932 INFO 9144 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
2023-01-09 22:56:12.934 INFO 9144 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 2 ms
2023-01-09 22:56:12.972 INFO 9144 --- [ Test worker] c.e.blog.controller.PostControllerTest : Started PostControllerTest in 7.047 seconds (JVM running for 10.256)
MockHttpServletRequest:
HTTP Method = PATCH
Request URI = /posts/1
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"51"]
Body = {"title":"블로그 수정","content":"부림동 "}
Session Attrs = {}
Handler:
Type = com.endofma.blog.controller.PostController
Method = com.endofma.blog.controller.PostController#edit(Long, PostEdit)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
2023-01-09 22:56:40.175 INFO 9144 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-01-09 22:56:40.175 INFO 9144 --- [ionShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2023-01-09 22:56:40.178 WARN 9144 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90121, SQLState: 90121
2023-01-09 22:56:40.179 ERROR 9144 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-01-09 22:56:40.179 WARN 9144 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90121, SQLState: 90121
2023-01-09 22:56:40.179 ERROR 9144 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-01-09 22:56:40.180 WARN 9144 --- [ionShutdownHook] o.s.b.f.support.DisposableBeanAdapter : Invocation of destroy method failed on bean with name 'entityManagerFactory': org.hibernate.exception.JDBCConnectionException: Unable to release JDBC Connection used for DDL execution
2023-01-09 22:56:40.180 INFO 9144 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2023-01-09 22:56:40.183 INFO 9144 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Disconnected from the target VM, address: 'localhost:60596', transport: 'socket'
BUILD SUCCESSFUL in 49s
4 actionable tasks: 1 executed, 3 up-to-date
PM 10:56:40: Execution finished ':test --tests "com.endofma.blog.controller.PostControllerTest.test7"'.
'Projects > blog' 카테고리의 다른 글
blog12: 예외처리1 (0) | 2023.01.10 |
---|---|
blog11: 게시글 삭제 (0) | 2023.01.10 |
blog10: 게시글 수정 1 (0) | 2023.01.09 |
blog09: 페이징 처리(QueryDSL) 2 (0) | 2023.01.04 |
blog09: 페이징 처리(QueryDSL) 1 (0) | 2023.01.04 |
Comments