Add article query

게시글 단건 조회 추가
This commit is contained in:
JiwonDev
2021-10-21 20:51:50 +09:00
committed by Jiwon
parent d5dd215dfd
commit 3af4ef973f
6 changed files with 133 additions and 1 deletions

View File

@@ -1,8 +1,11 @@
package com.yam.app.article.application;
import com.yam.app.article.domain.ArticleNotFoundException;
import com.yam.app.article.domain.ArticleReader;
import com.yam.app.article.domain.WriteArticleProcessor;
import com.yam.app.article.presentation.ArticlePreviewResponse;
import com.yam.app.article.presentation.ArticleResponse;
import com.yam.app.article.presentation.TagResponse;
import com.yam.app.article.presentation.WriteArticleCommand;
import java.util.List;
import java.util.stream.Collectors;
@@ -38,4 +41,26 @@ public class ArticleFacade {
dto.getStatus())
).collect(Collectors.toList());
}
@Transactional(readOnly = true)
public ArticleResponse findById(Long articleId) {
var article = articleReader.findById(articleId).orElseThrow(
() -> new ArticleNotFoundException(articleId));
return ArticleResponse.builder()
.id(article.getId())
.authorId(article.getAuthorId())
.title(article.getTitle())
.content(article.getContent())
.image(article.getImage())
.createdAt(article.getCreatedAt())
.modifiedAt(article.getModifiedAt())
.tags(
article.getTags().stream()
.map(a -> TagResponse.of(a.getTag().getId(), a.getTag().getName()))
.collect(Collectors.toList())
)
.build();
}
}

View File

@@ -5,6 +5,7 @@ import com.yam.app.common.ApiResult;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -29,4 +30,9 @@ public final class ArticleQueryApi {
return ResponseEntity.ok(
ApiResult.success(articleFacade.findAll(offset, limit)));
}
@GetMapping("/api/articles/{articleId}")
public ResponseEntity<ArticleResponse> showArticle(@PathVariable Long articleId) {
return ResponseEntity.ok(articleFacade.findById(articleId));
}
}

View File

@@ -0,0 +1,34 @@
package com.yam.app.article.presentation;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public final class ArticleResponse {
private final Long id;
private final Long authorId;
private final String title;
private final String content;
private final String image;
private final LocalDateTime createdAt;
private final LocalDateTime modifiedAt;
private final List<TagResponse> tags;
private ArticleResponse(Long id, Long authorId, String title, String content, String image,
LocalDateTime createdAt, LocalDateTime modifiedAt,
List<TagResponse> tags) {
this.id = id;
this.authorId = authorId;
this.title = title;
this.content = content;
this.image = image;
this.createdAt = createdAt;
this.modifiedAt = modifiedAt;
this.tags = tags;
}
}

View File

@@ -0,0 +1,20 @@
package com.yam.app.article.presentation;
import lombok.Getter;
@Getter
public final class TagResponse {
private final Long id;
private final String name;
private TagResponse(Long id, String name) {
this.id = id;
this.name = name;
}
public static TagResponse of(Long id, String name) {
return new TagResponse(id, name);
}
}

View File

@@ -4,6 +4,8 @@ public final class ArticleApiUri {
public static final String WRITE_ARTICLE = "/api/articles/write";
public static final String FIND_ALL = "/api/articles/all";
public static final String FIND_BY_ID = "/api/articles/";
private ArticleApiUri() {}
private ArticleApiUri() {
}
}

View File

@@ -0,0 +1,45 @@
package com.yam.app.article.presentation;
import static com.yam.app.article.presentation.ArticleApiUri.FIND_BY_ID;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.yam.app.article.application.ArticleFacade;
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.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
@DisplayName("Article Qurey HTTP API")
@WebMvcTest(ArticleQueryApi.class)
@ActiveProfiles("test")
class ArticleQueryApiTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ArticleFacade articleFacade;
@Test
@DisplayName("인증되지 않은 사용자가 게시글 조회 요청을 보냈다면 401에러를 반환한다.")
void unauthenticated_user_request() throws Exception {
//Act
final var actions = mockMvc.perform(get(FIND_BY_ID + 1)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
);
//Assert
actions
.andExpect(status().isUnauthorized())
.andExpect(jsonPath("$.success").value(false))
.andExpect(jsonPath("$.data").doesNotExist())
.andExpect(jsonPath("$.message").value("Unauthorized request"));
}
}