Skip to content

Commit

Permalink
Merge pull request #220 from bucket-back/OMCT-345-test-vote-reader
Browse files Browse the repository at this point in the history
[OMCT-345] �VoteReader 단위테스트 추가
  • Loading branch information
Yiseull authored Jan 8, 2024
2 parents aa26c7a + 43e60eb commit 4e1a308
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void deleteVote(final Long voteId) {

public VoteGetServiceResponse getVote(final Long voteId) {
final Long memberId = memberUtils.getCurrentMemberId();
final VoteDetail detail = voteReader.read(voteId, memberId);
final VoteDetail detail = voteReader.readDetail(voteId, memberId);

return VoteGetServiceResponse.from(detail);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Vote read(final Long voteId) {
}

@Transactional(readOnly = true)
public VoteDetail read(
public VoteDetail readDetail(
final Long voteId,
final Long memberId
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package com.programmers.bucketback.domains.vote.implementation;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.programmers.bucketback.common.cursor.CursorPageParameters;
import com.programmers.bucketback.common.cursor.CursorPageParametersBuilder;
import com.programmers.bucketback.common.cursor.CursorSummary;
import com.programmers.bucketback.common.cursor.CursorUtils;
import com.programmers.bucketback.common.model.Hobby;
import com.programmers.bucketback.domains.item.domain.Item;
import com.programmers.bucketback.domains.item.domain.ItemBuilder;
import com.programmers.bucketback.domains.item.implementation.ItemReader;
import com.programmers.bucketback.domains.item.model.ItemInfo;
import com.programmers.bucketback.domains.vote.domain.Vote;
import com.programmers.bucketback.domains.vote.domain.VoteBuilder;
import com.programmers.bucketback.domains.vote.model.VoteCursorSummary;
import com.programmers.bucketback.domains.vote.model.VoteCursorSummaryBuilder;
import com.programmers.bucketback.domains.vote.model.VoteDetail;
import com.programmers.bucketback.domains.vote.model.VoteDetailInfo;
import com.programmers.bucketback.domains.vote.model.VoteSortCondition;
import com.programmers.bucketback.domains.vote.model.VoteStatusCondition;
import com.programmers.bucketback.domains.vote.model.VoteSummary;
import com.programmers.bucketback.domains.vote.model.VoteSummaryBuilder;
import com.programmers.bucketback.domains.vote.repository.VoteRepository;
import com.programmers.bucketback.error.EntityNotFoundException;

@ExtendWith(MockitoExtension.class)
class VoteReaderTest {

@InjectMocks
private VoteReader voteReader;

@Mock
private VoteCounter voteCounter;

@Mock
private VoteRepository voteRepository;

@Mock
private VoterReader voterReader;

@Mock
private ItemReader itemReader;

@Nested
@DisplayName("투표 엔티티 조회 테스트")
class ReadTest {
@Test
@DisplayName("voteId와 일치하는 투표를 반환한다.")
void readVoteTest() {
// given
final Vote vote = VoteBuilder.build();

given(voteRepository.findById(anyLong()))
.willReturn(Optional.of(vote));

// when
final Vote readVote = voteReader.read(vote.getId());

// then
assertThat(readVote).usingRecursiveComparison()
.isEqualTo(vote);
}

@Test
@DisplayName("voteId와 일치하는 투표가 없으면 예외가 발생한다.")
void occurExceptionIfNoVoteTest() {
// given
final Long wrongVoteId = 0L;

given(voteRepository.findById(anyLong()))
.willReturn(Optional.empty());

// when & then
assertThatThrownBy(
() -> voteReader.read(wrongVoteId)
).isInstanceOf(EntityNotFoundException.class);
}
}

@Test
@DisplayName("투표 상세 조회한다.")
void readDetailTest() {
// given
final Long memberId = 1L;
final Vote vote = VoteBuilder.build();
final Long item1Id = vote.getItem1Id();
final Long item2Id = vote.getItem2Id();

final Item item1 = ItemBuilder.build(item1Id);
final Item item2 = ItemBuilder.build(item2Id);
final ItemInfo item1Info = ItemInfo.from(item1);
final ItemInfo item2Info = ItemInfo.from(item2);

final int item1Votes = 4;
final int item2Votes = 5;
final VoteDetailInfo voteInfo = VoteDetailInfo.of(vote, item1Votes, item2Votes);

given(voteRepository.findById(anyLong()))
.willReturn(Optional.of(vote));
given(itemReader.read(item1Id))
.willReturn(item1);
given(itemReader.read(item2Id))
.willReturn(item2);
given(voteCounter.count(any(Vote.class), eq(item1Id)))
.willReturn(item1Votes);
given(voteCounter.count(any(Vote.class), eq(item2Id)))
.willReturn(item2Votes);
given(voterReader.readItemId(any(Vote.class), anyLong()))
.willReturn(item1Id);

// when
final VoteDetail result = voteReader.readDetail(vote.getId(), memberId);

// then
assertThat(result.voteInfo()).isEqualTo(voteInfo);
assertThat(result.item1Info()).isEqualTo(item1Info);
assertThat(result.item2Info()).isEqualTo(item2Info);
assertThat(result.selectedItemId()).isEqualTo(item1Id);
}

@Test
@DisplayName("검색 조건에 맞는 투표 목록을 조회한다.")
void readByConditionTest() {
// given
final int DEFAULT_PAGING_SIZE = 20;
final Hobby hobby = Hobby.BASKETBALL;
final VoteStatusCondition statusCondition = VoteStatusCondition.COMPLETED;
final VoteSortCondition sortCondition = VoteSortCondition.RECENT;
final CursorPageParameters parameters = CursorPageParametersBuilder.build();
final Long memberId = 1L;

final int pageSize = parameters.size() == null ? DEFAULT_PAGING_SIZE : parameters.size();
final List<VoteCursorSummary> voteCursorSummaries = VoteCursorSummaryBuilder.buildMany(pageSize);
final List<VoteSummary> voteSummaries = VoteSummaryBuilder.buildMany(voteCursorSummaries);
final CursorSummary<VoteSummary> cursorSummary = CursorUtils.getCursorSummaries(voteSummaries);

given(voteRepository.findAllByCursor(
any(Hobby.class),
eq(statusCondition),
eq(sortCondition),
eq(null),
anyLong(),
eq(parameters.cursorId()),
eq(pageSize)
)).willReturn(voteCursorSummaries);

given(itemReader.read(anyLong()))
.will(invocation -> {
final Long givenItemId = invocation.getArgument(0);
return ItemBuilder.build(givenItemId);
});

// when
final CursorSummary<VoteSummary> result = voteReader.readByCursor(
hobby,
statusCondition,
sortCondition,
null,
parameters,
memberId
);

// then
assertThat(result).isEqualTo(cursorSummary);
}

@Test
@DisplayName("키워드가 투표 아이템 이름에 들어가는 투표의 개수를 센다.")
void countByKeywordTest() {
// given
final String keyword = "농구공";
final long count = 10;

given(voteRepository.countByKeyword(anyString()))
.willReturn(count);

// when
final long result = voteReader.countByKeyword(keyword);

// then
assertThat(result).isEqualTo(count);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.programmers.bucketback.domains.vote.domain;

import java.util.ArrayList;
import java.util.List;

import org.springframework.test.util.ReflectionTestUtils;

import com.programmers.bucketback.common.model.Hobby;
Expand Down Expand Up @@ -27,11 +30,33 @@ public static Vote build(final Long memberId) {
return vote;
}

public static List<Vote> buildMany(final int size) {
final List<Vote> votes = new ArrayList<>();
for (int i = 0; i < size; i++) {
final Vote vote = build();
setVoteId(vote, (long)(i + 1));
votes.add(vote);
}

return votes;
}

private static void setVoteId(final Vote vote) {
ReflectionTestUtils.setField(
vote,
"id",
1L
);
}

private static void setVoteId(
final Vote vote,
final Long id
) {
ReflectionTestUtils.setField(
vote,
"id",
id
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class VoterBuilder {
public static List<Voter> buildMany(
final int size,
final long size,
final Vote vote,
final Long itemId
) {
return LongStream.range(0, size)
return LongStream.range(1, size + 1)
.mapToObj(i -> {
Voter voter = VoterBuilder.build(vote, i + 1, itemId);
setVoterId(voter, i + 1);
Voter voter = VoterBuilder.build(vote, i, itemId);
setVoterId(voter, i);

return voter;
})
Expand All @@ -30,7 +30,7 @@ public static Voter build(
final Long memberId,
final Long itemId
) {
Voter voter = new Voter(vote, memberId, itemId);
final Voter voter = new Voter(vote, memberId, itemId);

setVoterId(voter, 1L);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.programmers.bucketback.domains.vote.model;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import com.programmers.bucketback.domains.vote.domain.Vote;
import com.programmers.bucketback.domains.vote.domain.VoteBuilder;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class VoteCursorSummaryBuilder {
public static List<VoteCursorSummary> buildMany(final int size) {
final List<Vote> votes = VoteBuilder.buildMany(size);
final List<VoteCursorSummary> voteCursorSummaries = new ArrayList<>();
for (final Vote vote: votes) {
final VoteInfo voteInfo = VoteInfo.builder()
.id(vote.getId())
.content(vote.getContent())
.startTime(vote.getStartTime())
.isVoting(false)
.participants(vote.getVoters().size())
.build();
final String cursorId = generateCursorId(vote);
final VoteCursorSummary voteCursorSummary = new VoteCursorSummary(voteInfo, vote.getItem1Id(), vote.getItem2Id(), cursorId);
voteCursorSummaries.add(voteCursorSummary);
}

return voteCursorSummaries;
}

private static String generateCursorId(final Vote vote) {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
final String formattedDate = vote.getStartTime().format(formatter);

return String.format("%s%s", formattedDate, String.format("%08d", vote.getId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.programmers.bucketback.domains.vote.model;

import java.util.List;

import com.programmers.bucketback.domains.item.domain.Item;
import com.programmers.bucketback.domains.item.domain.ItemBuilder;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class VoteSummaryBuilder {
public static List<VoteSummary> buildMany(final List<VoteCursorSummary> voteSummaries) {
return voteSummaries.stream()
.map(voteCursorSummary -> {
final Long item1Id = voteCursorSummary.item1Id();
final Item item1 = ItemBuilder.build(item1Id);
final Long item2Id = voteCursorSummary.item2Id();
final Item item2 = ItemBuilder.build(item2Id);

return VoteSummary.of(voteCursorSummary, item1, item2);
})
.toList();
}
}

0 comments on commit 4e1a308

Please sign in to comment.