Skip to content

Commit

Permalink
feat: 블로그 단일 조회 기능 구현 (#91)
Browse files Browse the repository at this point in the history
* [#23] feat: 블로그 정보 조회 서비스 작성

* [#23] feat: 블로그 정보 조회 API 작성
  • Loading branch information
shin-mallang authored Nov 22, 2023
1 parent 297ab35 commit 3bd4bd7
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/main/java/com/mallang/auth/config/AuthConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ private AuthInterceptor setUpAuthInterceptor() {
UriAndMethodAndParamCondition.builder()
.uriPatterns(Set.of(
"/members/*",
"/blogs",
"/posts/**",
"/categories",
"/comments",
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/mallang/blog/presentation/BlogController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import com.mallang.auth.presentation.support.Auth;
import com.mallang.blog.application.BlogService;
import com.mallang.blog.presentation.request.OpenBlogRequest;
import com.mallang.blog.query.BlogQueryService;
import com.mallang.blog.query.response.BlogResponse;
import java.net.URI;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
Expand All @@ -17,6 +21,7 @@
public class BlogController {

private final BlogService blogService;
private final BlogQueryService blogQueryService;

@PostMapping
public ResponseEntity<Void> open(
Expand All @@ -26,4 +31,11 @@ public ResponseEntity<Void> open(
Long blogId = blogService.open(request.toCommand(memberId));
return ResponseEntity.created(URI.create("/blogs/" + blogId)).build();
}

@GetMapping
public ResponseEntity<BlogResponse> findByName(
@RequestParam("blogName") String blogName
) {
return ResponseEntity.ok(blogQueryService.findByName(blogName));
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/mallang/blog/query/BlogQueryService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mallang.blog.query;

import com.mallang.blog.query.dao.BlogDao;
import com.mallang.blog.query.response.BlogResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class BlogQueryService {

private final BlogDao blogDao;

public BlogResponse findByName(String blogName) {
return blogDao.find(blogName);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/mallang/blog/query/dao/BlogDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mallang.blog.query.dao;

import com.mallang.blog.query.response.BlogResponse;
import com.mallang.blog.query.support.BlogQuerySupport;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Component
public class BlogDao {

private final BlogQuerySupport blogQuerySupport;

public BlogResponse find(String blogName) {
return BlogResponse.from(blogQuerySupport.getWithOwnerByName(blogName));
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/mallang/blog/query/response/BlogResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.mallang.blog.query.response;

import com.mallang.auth.domain.Member;
import com.mallang.blog.domain.Blog;
import lombok.Builder;

@Builder
public record BlogResponse(
Long id,
String name,
OwnerResponse owner
) {

public static BlogResponse from(Blog blog) {
return BlogResponse.builder()
.id(blog.getId())
.name(blog.getName())
.owner(OwnerResponse.from(blog.getOwner()))
.build();
}

@Builder
public record OwnerResponse(
Long memberId,
String nickname,
String profileImageUrl
) {
public static OwnerResponse from(Member owner) {
return OwnerResponse.builder()
.memberId(owner.getId())
.nickname(owner.getNickname())
.profileImageUrl(owner.getProfileImageUrl())
.build();
}
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/mallang/blog/query/support/BlogQuerySupport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mallang.blog.query.support;

import com.mallang.blog.domain.Blog;
import com.mallang.blog.exception.NotFoundBlogException;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface BlogQuerySupport extends JpaRepository<Blog, Long> {

default Blog getWithOwnerByName(String blogName) {
return findWithOwnerByName(blogName).orElseThrow(NotFoundBlogException::new);
}

@Query("SELECT b FROM Blog b JOIN FETCH b.owner WHERE b.name.value = :blogName")
Optional<Blog> findWithOwnerByName(String blogName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ public class BlogAcceptanceSteps {
.then().log().all()
.extract();
}

public static ExtractableResponse<Response> 블로그_정보_조회_요청(String 블로그_이름) {
return given()
.queryParam("blogName", 블로그_이름)
.get("/blogs")
.then().log().all()
.extract();
}
}
111 changes: 73 additions & 38 deletions src/test/java/com/mallang/acceptance/blog/BlogAcceptanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,67 +8,102 @@
import static com.mallang.acceptance.AcceptanceSteps.중복됨;
import static com.mallang.acceptance.auth.AuthAcceptanceSteps.회원가입과_로그인_후_세션_ID_반환;
import static com.mallang.acceptance.blog.BlogAcceptanceSteps.블로그_개설_요청;
import static com.mallang.acceptance.blog.BlogAcceptanceSteps.블로그_정보_조회_요청;
import static org.assertj.core.api.Assertions.assertThat;

import com.mallang.acceptance.AcceptanceTest;
import com.mallang.blog.query.response.BlogResponse;
import com.mallang.blog.query.response.BlogResponse.OwnerResponse;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

@DisplayName("블로그 인수테스트")
@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(ReplaceUnderscores.class)
class BlogAcceptanceTest extends AcceptanceTest {

@Test
void 블로그를_개설한다() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
@Nested
class 블로그_조회_API {

// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "mallang-blog");
@Test
void 블로그를_개설한다() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");

// then
응답_상태를_검증한다(응답, 생성됨);
값이_존재한다(ID를_추출한다(응답));
}
// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "mallang-blog");

@Test
void 블로그_이름이_올바르지_않으면_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
// then
응답_상태를_검증한다(응답, 생성됨);
값이_존재한다(ID를_추출한다(응답));
}

// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "한글-이름");
@Test
void 블로그_이름이_올바르지_않으면_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");

// then
응답_상태를_검증한다(응답, 잘못된_요청);
}
// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "한글-이름");

// then
응답_상태를_검증한다(응답, 잘못된_요청);
}

@Test
void 동일한_이름의_블로그가_이미_존재하면_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
var 안말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("안말랑");
블로그_개설_요청(말랑_세션_ID, "mallang-log");

@Test
void 동일한_이름의_블로그가_이미_존재하면_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
var 안말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("안말랑");
블로그_개설_요청(말랑_세션_ID, "mallang-log");
// when
var 응답 = 블로그_개설_요청(안말랑_세션_ID, "mallang-log");

// when
var 응답 = 블로그_개설_요청(안말랑_세션_ID, "mallang-log");
// then
응답_상태를_검증한다(응답, 중복됨);
}

// then
응답_상태를_검증한다(응답, 중복됨);
@Test
void 이미_개설한_블로그가_있는_경우_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
블로그_개설_요청(말랑_세션_ID, "mallang-log");

// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "mallang-2");

// then
응답_상태를_검증한다(응답, 잘못된_요청);
}
}

@Test
void 이미_개설한_블로그가_있는_경우_예외() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
블로그_개설_요청(말랑_세션_ID, "mallang-log");
@Nested
class 블로그_정보_조회_시 {

@Test
void 블로그_정보를_조회한다() {
// given
var 말랑_세션_ID = 회원가입과_로그인_후_세션_ID_반환("말랑");
var 블로그_ID = ID를_추출한다(블로그_개설_요청(말랑_세션_ID, "mallang-log"));
var 블로그_이름 = "mallang-log";

// when
var 응답 = 블로그_개설_요청(말랑_세션_ID, "mallang-2");
// when
var 응답 = 블로그_정보_조회_요청(블로그_이름);

// then
응답_상태를_검증한다(응답, 잘못된_요청);
// then
BlogResponse blogResponse = 응답.as(BlogResponse.class);
assertThat(blogResponse)
.usingRecursiveComparison()
.ignoringFields("owner.memberId")
.isEqualTo(new BlogResponse(
블로그_ID,
블로그_이름,
new OwnerResponse(null, "말랑", "말랑")
));
}
}
}

0 comments on commit 3bd4bd7

Please sign in to comment.