Skip to content

Commit

Permalink
[Weekly/11/Test/like] Like리팩터링 및 Event Unit Test 수정 (#97)
Browse files Browse the repository at this point in the history
* test: Event Unit Test 리팩터링

* feat: Like 리팩터링
  • Loading branch information
ariimo authored Nov 8, 2024
1 parent 9772c6f commit 03863bc
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.ktc2.cokaen.wouldyouin.like.api;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.ktc2.cokaen.wouldyouin._common.api.ApiResponse;
import org.ktc2.cokaen.wouldyouin._common.api.ApiResponseBody;
import org.ktc2.cokaen.wouldyouin._common.config.ParamDefaults;
import org.ktc2.cokaen.wouldyouin.auth.Authorize;
import org.ktc2.cokaen.wouldyouin.auth.MemberIdentifier;
import org.ktc2.cokaen.wouldyouin.like.application.LikeResponse;
import org.ktc2.cokaen.wouldyouin.like.application.LikeServiceFactory;
import org.ktc2.cokaen.wouldyouin.like.application.dto.LikeResponse;
import org.ktc2.cokaen.wouldyouin.like.application.dto.LikeToggleResponse;
import org.ktc2.cokaen.wouldyouin.member.persist.MemberType;
import org.springframework.http.HttpStatus;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -26,22 +27,24 @@ public class LikeController {

private final LikeServiceFactory likeServiceFactory;

// Todo: 와일드카드 수정
// Todo: api 요청시 create, delete를 분리하지말고 토글방식으로 하면 어떨지

@GetMapping
public ResponseEntity<ApiResponseBody<List<LikeResponse>>> getLikes(@Authorize(MemberType.normal) MemberIdentifier identifier, @RequestParam("type") MemberType memberType) {
return ApiResponse.ok(likeServiceFactory.getLikeServiceFrom(memberType).getLikes(identifier.id()));
public ResponseEntity<ApiResponseBody<Slice<LikeResponse>>> getLikes(
@Authorize(MemberType.normal) MemberIdentifier identifier,
@RequestParam("type") MemberType memberType,
@RequestParam(defaultValue = ParamDefaults.PAGE) Integer page,
@RequestParam(defaultValue = ParamDefaults.PAGE_SIZE) Integer size,
@RequestParam(defaultValue = ParamDefaults.LAST_ID) Long lastId
) {
return ApiResponse.ok(
likeServiceFactory.getLikeServiceFrom(memberType)
.getLikes(identifier.id(), PageRequest.of(page, size), lastId));
}

@PostMapping("/{targetMemberId}")
public ResponseEntity<ApiResponseBody<LikeResponse>> createLike(@Authorize(MemberType.normal) MemberIdentifier identifier, @PathVariable("targetMemberId") Long targetId) {
return ApiResponse.created(likeServiceFactory.getLikeServiceFrom(targetId).create(identifier.id(), targetId));
}

@DeleteMapping("/{targetMemberId}")
public ResponseEntity<ApiResponseBody<Void>> deleteLike(@Authorize(MemberType.normal) MemberIdentifier identifier, @PathVariable("targetMemberId") Long targetId) {
likeServiceFactory.getLikeServiceFrom(targetId).delete(identifier.id(), targetId);
return ApiResponse.noContent();
public ResponseEntity<ApiResponseBody<LikeToggleResponse>> createOrDeleteLike(
@Authorize(MemberType.normal) MemberIdentifier identifier,
@PathVariable("targetMemberId") Long targetId) {
return ApiResponse.created(
likeServiceFactory.getLikeServiceFrom(targetId).toggleLike(identifier.id(), targetId));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package org.ktc2.cokaen.wouldyouin.like.application;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.ktc2.cokaen.wouldyouin.like.application.dto.LikeResponse;
import org.ktc2.cokaen.wouldyouin.like.application.dto.LikeToggleResponse;
import org.ktc2.cokaen.wouldyouin.like.persist.Like;
import org.ktc2.cokaen.wouldyouin.like.persist.LikeRepository;
import org.ktc2.cokaen.wouldyouin.member.application.LikeableMemberGetterFactory;
import org.ktc2.cokaen.wouldyouin.member.application.MemberService;
import org.ktc2.cokaen.wouldyouin.member.persist.LikeableMember;
import org.ktc2.cokaen.wouldyouin.member.persist.Member;
import org.ktc2.cokaen.wouldyouin.member.persist.MemberType;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -20,44 +23,38 @@ public abstract class LikeService<LikeType extends Like<? extends LikeableMember
private final MemberService memberService;

protected abstract LikeRepository<LikeType> getLikeRepository();

protected abstract LikeType toEntity(Member member, LikeableMember targetLikableMember);

public abstract MemberType getTargetLikeableMemberType();

@Transactional(readOnly = true)
public List<LikeResponse> getLikes(Long memberId) {
return getLikeRepository().findAllByMember(memberService.getByIdOrThrow(memberId))
.stream()
.map(Like::getLikeableMember)
.map(LikeResponse::from)
.toList();
public Slice<LikeResponse> getLikes(Long memberId, Pageable pageable, Long lastId) {
return getLikeRepository().findAllByMember(
memberService.getByIdOrThrow(memberId), lastId, pageable)
.map(like -> LikeResponse.from(like.getLikeableMember()));
}

@Transactional
public LikeResponse create(Long memberId, Long targetMemberId) {
public LikeToggleResponse toggleLike(Long memberId, Long targetMemberId) {
Member member = memberService.getByIdOrThrow(memberId);
LikeableMember targetLikeableMember = getLikeableMemberByIdOrThrow(targetMemberId);
getLikeRepository().findByMemberAndLikeableMember(member, targetLikeableMember)
.ifPresent(x -> { throw new RuntimeException("이미 좋아요한 사용자입니다."); });

targetLikeableMember.increaseLikes();
return LikeResponse.from(getLikeRepository()
.save(toEntity(member, targetLikeableMember))
.getLikeableMember());
}

@Transactional
public void delete(Long memberId, Long targetMemberId) {
Member member = memberService.getByIdOrThrow(memberId);
LikeableMember targetLikeableMember = getLikeableMemberByIdOrThrow(targetMemberId);
LikeType like = getLikeRepository().findByMemberAndLikeableMember(member, targetLikeableMember)
.orElseThrow(() -> new RuntimeException("해당 사용자를 좋아요하지 않았습니다."));

targetLikeableMember.decreaseLikes();
getLikeRepository().delete(like);
return getLikeRepository().findByMemberAndLikeableMember(member, targetLikeableMember)
.map(like -> {
targetLikeableMember.decreaseLikes();
getLikeRepository().delete(like);
return LikeToggleResponse.from(false);
})
.orElseGet(() -> {
targetLikeableMember.increaseLikes();
getLikeRepository().save(toEntity(member, targetLikeableMember));
return LikeToggleResponse.from(true);
});
}

@Transactional(readOnly = true)
protected LikeableMember getLikeableMemberByIdOrThrow(Long likeableMemberId) {
return likeableMemberGetterFactory.get(getTargetLikeableMemberType()).getByIdOrThrow(likeableMemberId);
return likeableMemberGetterFactory.get(getTargetLikeableMemberType())
.getByIdOrThrow(likeableMemberId);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.ktc2.cokaen.wouldyouin.like.application;
package org.ktc2.cokaen.wouldyouin.like.application.dto;

import java.util.List;
import lombok.AccessLevel;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.ktc2.cokaen.wouldyouin.like.application.dto;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.ktc2.cokaen.wouldyouin.member.persist.LikeableMember;

@Getter
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class LikeToggleResponse {
private final boolean isLiked;

public static LikeToggleResponse from(boolean state) {
return LikeToggleResponse.builder()
.isLiked(state)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package org.ktc2.cokaen.wouldyouin.like.persist;


import java.util.List;
import java.util.Optional;
import org.ktc2.cokaen.wouldyouin.member.persist.LikeableMember;
import org.ktc2.cokaen.wouldyouin.member.persist.Member;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface LikeRepository <LikeType extends Like<? extends LikeableMember>> extends JpaRepository<LikeType, Long> {

Optional<LikeType> findByMemberAndLikeableMember(Member member, LikeableMember likeableMember);
List<LikeType> findAllByMember(Member member);

@Query("SELECT l FROM #{#entityName} l " +
"JOIN FETCH l.member m " +
"JOIN FETCH l.likeableMember lm " +
"WHERE l.member.id = :member " +
"AND l.id < :lastId " +
"ORDER BY l.id DESC")
Slice<LikeType> findAllByMember(Member member, Long lastId, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,18 @@ void getEventsByFilterOrderByDistanceAsc() throws Exception {
// given
LocationFilter locationFilter = new LocationFilter(0.0, 0.0, 10.0, 10.0);
Location currentLocation = new Location(3.0, 2.0);
String title = "testTitle";
Category category = Category.공예;
Area area = Area.광주;
int pageNumber = 1; // 교수님
int pageSize = 10; //
int pageNumber = 1;
int pageSize = 10;
Long lastId = 1L;
Pageable pageable = PageRequest.of(pageNumber, pageSize);

given(eventService.getAllByFilterOrderByDistanceAsc(
locationFilter,
currentLocation,
title,
category,
area,
pageable,
Expand All @@ -115,8 +117,9 @@ void getEventsByFilterOrderByDistanceAsc() throws Exception {
.param("endLongitude", locationFilter.getEndLongitude().toString())
.param("latitude", currentLocation.getLatitude().toString())
.param("longitude", currentLocation.getLongitude().toString())
.param("category", category.toString()) // enum을 문자열로 변환하여 설정
.param("area", area.toString()) // enum을 문자열로 변환하여 설정
.param("title", title)
.param("category", category.toString())
.param("area", area.toString())
.param("page", String.valueOf(pageNumber))
.param("size", String.valueOf(pageSize))
.param("lastId", String.valueOf(lastId))
Expand All @@ -127,6 +130,7 @@ void getEventsByFilterOrderByDistanceAsc() throws Exception {
then(eventService).should(times(1)).getAllByFilterOrderByDistanceAsc(
any(LocationFilter.class),
any(Location.class),
eq(title),
eq(category),
eq(area),
eq(pageable),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
import org.ktc2.cokaen.wouldyouin._common.vo.Area;
import org.ktc2.cokaen.wouldyouin._common.vo.Category;
import org.ktc2.cokaen.wouldyouin._common.vo.Location;
import org.ktc2.cokaen.wouldyouin._global.TestData.EventDomain;
import org.ktc2.cokaen.wouldyouin.curation.api.dto.LocationFilter;
import org.ktc2.cokaen.wouldyouin.event.api.dto.EventCreateRequest;
import org.ktc2.cokaen.wouldyouin.event.api.dto.EventEditRequest;
import org.ktc2.cokaen.wouldyouin.event.application.EventService;
import org.ktc2.cokaen.wouldyouin.event.persist.Event;
import org.ktc2.cokaen.wouldyouin.event.persist.EventRepository;
import org.ktc2.cokaen.wouldyouin._global.TestData.EventDomain;
import org.ktc2.cokaen.wouldyouin.member.application.HostService;
import org.ktc2.cokaen.wouldyouin.member.application.MemberService;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.PageRequest;
Expand Down Expand Up @@ -62,6 +61,7 @@ void getAllByFilterOrderByDistanceAsc() {
// given
LocationFilter location = new LocationFilter();
Location currentLocation = new Location(3.0, 2.0);
String title = "testTitle";
Category category = Category.공예;
Area area = Area.광주;
int pageNumber = 1;
Expand All @@ -71,18 +71,18 @@ void getAllByFilterOrderByDistanceAsc() {
given(eventRepository.findAllByFilterOrderByDistance(location.getStartLatitude(),
location.getStartLongitude(),
location.getEndLatitude(), location.getEndLongitude(), currentLocation.getLatitude(),
currentLocation.getLongitude(),
category, area, pageable)).willReturn(new SliceImpl<>(List.of()));
currentLocation.getLongitude(), title, category, area, pageable)).willReturn(
new SliceImpl<>(List.of()));

// when
eventService.getAllByFilterOrderByDistanceAsc(location, currentLocation, category, area,
pageable, lastId);
eventService.getAllByFilterOrderByDistanceAsc(location, currentLocation, title, category,
area, pageable, lastId);

// then
then(eventRepository).should(times(1))
.findAllByFilterOrderByDistance(any(Double.class), any(Double.class), any(Double.class),
any(Double.class), any(Double.class), any(Double.class),
any(Category.class), any(Area.class), any(Pageable.class));
any(String.class), any(Category.class), any(Area.class), any(Pageable.class));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.ktc2.cokaen.wouldyouin.like;

public class LikeControllerUnitTest
{

}

0 comments on commit 03863bc

Please sign in to comment.