diff --git a/src/main/java/com/moabam/api/application/ItemService.java b/src/main/java/com/moabam/api/application/ItemService.java index 9d9aca77..4ba1203e 100644 --- a/src/main/java/com/moabam/api/application/ItemService.java +++ b/src/main/java/com/moabam/api/application/ItemService.java @@ -1,16 +1,20 @@ package com.moabam.api.application; +import static com.moabam.global.error.model.ErrorMessage.*; + import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.moabam.api.domain.entity.Inventory; import com.moabam.api.domain.entity.Item; import com.moabam.api.domain.entity.enums.ItemType; import com.moabam.api.domain.repository.InventorySearchRepository; import com.moabam.api.domain.repository.ItemSearchRepository; import com.moabam.api.dto.ItemMapper; import com.moabam.api.dto.ItemsResponse; +import com.moabam.global.error.exception.NotFoundException; import lombok.RequiredArgsConstructor; @@ -28,4 +32,18 @@ public ItemsResponse getItems(Long memberId, ItemType type) { return ItemMapper.toItemsResponse(purchasedItems, notPurchasedItems); } + + @Transactional + public void selectItem(Long memberId, Long itemId) { + Inventory inventory = getInventory(memberId, itemId); + + inventorySearchRepository.findDefault(memberId, inventory.getItemType()) + .ifPresent(Inventory::deselect); + inventory.select(); + } + + private Inventory getInventory(Long memberId, Long itemId) { + return inventorySearchRepository.findOne(memberId, itemId) + .orElseThrow(() -> new NotFoundException(INVENTORY_NOT_FOUND)); + } } diff --git a/src/main/java/com/moabam/api/domain/entity/Inventory.java b/src/main/java/com/moabam/api/domain/entity/Inventory.java index 4921ab7d..dd493564 100644 --- a/src/main/java/com/moabam/api/domain/entity/Inventory.java +++ b/src/main/java/com/moabam/api/domain/entity/Inventory.java @@ -4,6 +4,7 @@ import org.hibernate.annotations.ColumnDefault; +import com.moabam.api.domain.entity.enums.ItemType; import com.moabam.global.common.entity.BaseTimeEntity; import jakarta.persistence.Column; @@ -49,4 +50,16 @@ private Inventory(Long memberId, Item item, boolean isDefault) { this.item = requireNonNull(item); this.isDefault = isDefault; } + + public ItemType getItemType() { + return this.item.getType(); + } + + public void select() { + this.isDefault = true; + } + + public void deselect() { + this.isDefault = false; + } } diff --git a/src/main/java/com/moabam/api/domain/repository/InventorySearchRepository.java b/src/main/java/com/moabam/api/domain/repository/InventorySearchRepository.java index e15c017c..44a17bda 100644 --- a/src/main/java/com/moabam/api/domain/repository/InventorySearchRepository.java +++ b/src/main/java/com/moabam/api/domain/repository/InventorySearchRepository.java @@ -4,9 +4,11 @@ import static com.moabam.api.domain.entity.QItem.*; import java.util.List; +import java.util.Optional; import org.springframework.stereotype.Repository; +import com.moabam.api.domain.entity.Inventory; import com.moabam.api.domain.entity.Item; import com.moabam.api.domain.entity.enums.ItemType; import com.moabam.global.common.util.DynamicQuery; @@ -20,6 +22,27 @@ public class InventorySearchRepository { private final JPAQueryFactory jpaQueryFactory; + public Optional findOne(Long memberId, Long itemId) { + return Optional.ofNullable( + jpaQueryFactory.selectFrom(inventory) + .where( + DynamicQuery.generateEq(memberId, inventory.memberId::eq), + DynamicQuery.generateEq(itemId, inventory.item.id::eq)) + .fetchOne() + ); + } + + public Optional findDefault(Long memberId, ItemType type) { + return Optional.ofNullable( + jpaQueryFactory.selectFrom(inventory) + .where( + DynamicQuery.generateEq(memberId, inventory.memberId::eq), + DynamicQuery.generateEq(type, inventory.item.type::eq), + inventory.isDefault.isTrue()) + .fetchOne() + ); + } + public List findItems(Long memberId, ItemType type) { return jpaQueryFactory.selectFrom(inventory) .join(inventory.item, item) diff --git a/src/main/java/com/moabam/api/presentation/ItemController.java b/src/main/java/com/moabam/api/presentation/ItemController.java index 47bd5880..3c297d3b 100644 --- a/src/main/java/com/moabam/api/presentation/ItemController.java +++ b/src/main/java/com/moabam/api/presentation/ItemController.java @@ -2,6 +2,8 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; @@ -25,4 +27,10 @@ public class ItemController { public ItemsResponse getItems(@RequestParam ItemType type) { return itemService.getItems(1L, type); } + + @PostMapping("/{itemId}/select") + @ResponseStatus(HttpStatus.OK) + public void selectItem(@PathVariable Long itemId) { + itemService.selectItem(1L, itemId); + } } diff --git a/src/main/java/com/moabam/global/error/model/ErrorMessage.java b/src/main/java/com/moabam/global/error/model/ErrorMessage.java index f6ffb13c..6572021a 100644 --- a/src/main/java/com/moabam/global/error/model/ErrorMessage.java +++ b/src/main/java/com/moabam/global/error/model/ErrorMessage.java @@ -28,6 +28,8 @@ public enum ErrorMessage { MEMBER_NOT_FOUND("존재하지 않는 회원입니다."), MEMBER_ROOM_EXCEED("참여할 수 있는 방의 개수가 모두 찼습니다."), + INVENTORY_NOT_FOUND("구매하지 않은 아이템은 적용할 수 없습니다."), + INVALID_BUG_COUNT("벌레 개수는 0 이상이어야 합니다."), INVALID_PRICE("가격은 0 이상이어야 합니다."), INVALID_QUANTITY("수량은 1 이상이어야 합니다."), diff --git a/src/test/java/com/moabam/api/application/AuthenticationServiceTest.java b/src/test/java/com/moabam/api/application/AuthenticationServiceTest.java index cd884e1a..deb900f6 100644 --- a/src/test/java/com/moabam/api/application/AuthenticationServiceTest.java +++ b/src/test/java/com/moabam/api/application/AuthenticationServiceTest.java @@ -26,10 +26,10 @@ import com.moabam.api.dto.AuthorizationTokenRequest; import com.moabam.api.dto.AuthorizationTokenResponse; import com.moabam.api.dto.OAuthMapper; -import com.moabam.fixture.AuthorizationResponseFixture; import com.moabam.global.config.OAuthConfig; import com.moabam.global.error.exception.BadRequestException; import com.moabam.global.error.model.ErrorMessage; +import com.moabam.support.fixture.AuthorizationResponseFixture; @ExtendWith(MockitoExtension.class) class AuthenticationServiceTest { diff --git a/src/test/java/com/moabam/api/application/BugServiceTest.java b/src/test/java/com/moabam/api/application/BugServiceTest.java index 416ba5fb..72c06ae6 100644 --- a/src/test/java/com/moabam/api/application/BugServiceTest.java +++ b/src/test/java/com/moabam/api/application/BugServiceTest.java @@ -1,5 +1,6 @@ package com.moabam.api.application; +import static com.moabam.support.fixture.MemberFixture.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; @@ -13,7 +14,6 @@ import com.moabam.api.domain.entity.Bug; import com.moabam.api.domain.entity.Member; import com.moabam.api.dto.BugResponse; -import com.moabam.fixture.MemberFixture; @ExtendWith(MockitoExtension.class) class BugServiceTest { @@ -29,7 +29,7 @@ class BugServiceTest { void get_bug_success() { // given Long memberId = 1L; - Member member = MemberFixture.member(); + Member member = member(); given(memberService.getById(memberId)).willReturn(member); // when diff --git a/src/test/java/com/moabam/api/application/ItemServiceTest.java b/src/test/java/com/moabam/api/application/ItemServiceTest.java index cc2b0a43..b07741a8 100644 --- a/src/test/java/com/moabam/api/application/ItemServiceTest.java +++ b/src/test/java/com/moabam/api/application/ItemServiceTest.java @@ -1,19 +1,23 @@ package com.moabam.api.application; -import static com.moabam.fixture.ItemFixture.*; +import static com.moabam.support.fixture.ItemFixture.*; import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.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.moabam.api.domain.entity.Inventory; import com.moabam.api.domain.entity.Item; import com.moabam.api.domain.entity.enums.ItemType; import com.moabam.api.domain.repository.InventorySearchRepository; @@ -21,6 +25,8 @@ import com.moabam.api.dto.ItemResponse; import com.moabam.api.dto.ItemsResponse; import com.moabam.global.common.util.StreamUtils; +import com.moabam.global.error.exception.NotFoundException; +import com.moabam.support.fixture.InventoryFixture; @ExtendWith(MockitoExtension.class) class ItemServiceTest { @@ -54,4 +60,45 @@ void get_products_success() { assertThat(purchasedItemNames).containsExactly(MORNING_SANTA_SKIN_NAME, MORNING_KILLER_SKIN_NAME); assertThat(response.notPurchasedItems()).isEmpty(); } + + @DisplayName("아이템을 적용한다.") + @Nested + class SelectItem { + + @DisplayName("성공한다.") + @Test + void success() { + // given + Long memberId = 1L; + Long itemId = 1L; + Inventory inventory = InventoryFixture.inventory(memberId, nightMageSkin()); + Inventory defaultInventory = InventoryFixture.inventory(memberId, nightMageSkin()); + ItemType itemType = inventory.getItemType(); + given(inventorySearchRepository.findOne(memberId, itemId)).willReturn(Optional.of(inventory)); + given(inventorySearchRepository.findDefault(memberId, itemType)).willReturn(Optional.of(defaultInventory)); + + // when + itemService.selectItem(memberId, itemId); + + // then + verify(inventorySearchRepository).findOne(memberId, itemId); + verify(inventorySearchRepository).findDefault(memberId, itemType); + assertFalse(defaultInventory.isDefault()); + assertTrue(inventory.isDefault()); + } + + @DisplayName("인벤토리 아이템이 아니면 예외가 발생한다.") + @Test + void exception() { + // given + Long memberId = 1L; + Long itemId = 1L; + given(inventorySearchRepository.findOne(memberId, itemId)).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy(() -> itemService.selectItem(memberId, itemId)) + .isInstanceOf(NotFoundException.class) + .hasMessage("구매하지 않은 아이템은 적용할 수 없습니다."); + } + } } diff --git a/src/test/java/com/moabam/api/application/ProductServiceTest.java b/src/test/java/com/moabam/api/application/ProductServiceTest.java index bb63597f..c4555b94 100644 --- a/src/test/java/com/moabam/api/application/ProductServiceTest.java +++ b/src/test/java/com/moabam/api/application/ProductServiceTest.java @@ -1,6 +1,6 @@ package com.moabam.api.application; -import static com.moabam.fixture.ProductFixture.*; +import static com.moabam.support.fixture.ProductFixture.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; diff --git a/src/test/java/com/moabam/api/domain/entity/MemberTest.java b/src/test/java/com/moabam/api/domain/entity/MemberTest.java index 1a947ac8..ab0df828 100644 --- a/src/test/java/com/moabam/api/domain/entity/MemberTest.java +++ b/src/test/java/com/moabam/api/domain/entity/MemberTest.java @@ -8,8 +8,8 @@ import org.junit.jupiter.api.Test; import com.moabam.api.domain.entity.enums.Role; -import com.moabam.fixture.MemberFixture; import com.moabam.global.common.util.BaseImageUrl; +import com.moabam.support.fixture.MemberFixture; class MemberTest { diff --git a/src/test/java/com/moabam/api/domain/repository/InventorySearchRepositoryTest.java b/src/test/java/com/moabam/api/domain/repository/InventorySearchRepositoryTest.java index 83463363..c8e78153 100644 --- a/src/test/java/com/moabam/api/domain/repository/InventorySearchRepositoryTest.java +++ b/src/test/java/com/moabam/api/domain/repository/InventorySearchRepositoryTest.java @@ -1,67 +1,109 @@ package com.moabam.api.domain.repository; -import static com.moabam.fixture.InventoryFixture.*; -import static com.moabam.fixture.ItemFixture.*; +import static com.moabam.support.fixture.InventoryFixture.*; +import static com.moabam.support.fixture.ItemFixture.*; +import static com.moabam.support.fixture.MemberFixture.*; import static org.assertj.core.api.Assertions.*; 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.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; +import com.moabam.api.domain.entity.Inventory; import com.moabam.api.domain.entity.Item; +import com.moabam.api.domain.entity.Member; import com.moabam.api.domain.entity.enums.ItemType; +import com.moabam.support.annotation.QuerydslRepositoryTest; -@SpringBootTest -@Transactional(readOnly = true) +@QuerydslRepositoryTest class InventorySearchRepositoryTest { + @Autowired + InventorySearchRepository inventorySearchRepository; + + @Autowired + MemberRepository memberRepository; + @Autowired ItemRepository itemRepository; @Autowired InventoryRepository inventoryRepository; - @Autowired - InventorySearchRepository inventorySearchRepository; + @DisplayName("인벤토리 아이템 목록을 조회한다.") + @Nested + class FindItems { + + @DisplayName("해당 타입의 아이템 목록을 구매일 순으로 정렬한다.") + @Test + void sorted_by_created_at_success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); + inventoryRepository.save(inventory(memberId, morningSantaSkin)); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); + inventoryRepository.save(inventory(memberId, morningKillerSkin)); + Item nightMageSkin = itemRepository.save(nightMageSkin()); + inventoryRepository.save(inventory(memberId, nightMageSkin)); + + // when + List actual = inventorySearchRepository.findItems(memberId, ItemType.MORNING); + + // then + assertThat(actual).hasSize(2) + .containsExactly(morningKillerSkin, morningSantaSkin); + } + + @DisplayName("해당 타입의 아이템이 없으면 빈 목록을 조회한다.") + @Test + void empty_success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); + inventoryRepository.save(inventory(memberId, morningSantaSkin)); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); + inventoryRepository.save(inventory(memberId, morningKillerSkin)); + + // when + List actual = inventorySearchRepository.findItems(memberId, ItemType.NIGHT); + + // then + assertThat(actual).isEmpty(); + } + } - @DisplayName("타입으로 인벤토리에 있는 아이템 목록을 구매일 순으로 조회한다.") + @DisplayName("인벤토리를 조회한다.") @Test - void find_items_success() { + void find_one_success() { // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); - inventoryRepository.save(inventory(memberId, morningSantaSkin)); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); - inventoryRepository.save(inventory(memberId, morningKillerSkin)); - Item nightMageSkin = itemRepository.save(nightMageSkin()); - inventoryRepository.save(inventory(memberId, nightMageSkin)); + Member member = memberRepository.save(member()); + Item item = itemRepository.save(nightMageSkin()); + Inventory inventory = inventoryRepository.save(inventory(member.getId(), item)); // when - List actual = inventorySearchRepository.findItems(memberId, ItemType.MORNING); + Optional actual = inventorySearchRepository.findOne(member.getId(), item.getId()); // then - assertThat(actual).hasSize(2) - .containsExactly(morningKillerSkin, morningSantaSkin); + assertThat(actual).isPresent().contains(inventory); } - @DisplayName("인벤토리에 해당하는 타입의 아이템이 없으면 빈 목록을 조회한다.") + @DisplayName("현재 적용된 인벤토리를 조회한다.") @Test - void find_empty_success() { + void find_default_success() { // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); - inventoryRepository.save(inventory(memberId, morningSantaSkin)); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); - inventoryRepository.save(inventory(memberId, morningKillerSkin)); + Member member = memberRepository.save(member()); + Item item = itemRepository.save(nightMageSkin()); + Inventory inventory = inventoryRepository.save(inventory(member.getId(), item)); + inventory.select(); // when - List actual = inventorySearchRepository.findItems(memberId, ItemType.NIGHT); + Optional actual = inventorySearchRepository.findDefault(member.getId(), inventory.getItemType()); // then - assertThat(actual).isEmpty(); + assertThat(actual).isPresent().contains(inventory); } } diff --git a/src/test/java/com/moabam/api/domain/repository/ItemSearchRepositoryTest.java b/src/test/java/com/moabam/api/domain/repository/ItemSearchRepositoryTest.java index c4d41b15..a1bc7751 100644 --- a/src/test/java/com/moabam/api/domain/repository/ItemSearchRepositoryTest.java +++ b/src/test/java/com/moabam/api/domain/repository/ItemSearchRepositoryTest.java @@ -1,96 +1,100 @@ package com.moabam.api.domain.repository; -import static com.moabam.fixture.InventoryFixture.*; -import static com.moabam.fixture.ItemFixture.*; +import static com.moabam.support.fixture.InventoryFixture.*; +import static com.moabam.support.fixture.ItemFixture.*; import static org.assertj.core.api.Assertions.*; import java.util.List; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; import com.moabam.api.domain.entity.Item; import com.moabam.api.domain.entity.enums.ItemType; +import com.moabam.support.annotation.QuerydslRepositoryTest; -@SpringBootTest -@Transactional(readOnly = true) +@QuerydslRepositoryTest class ItemSearchRepositoryTest { @Autowired - ItemRepository itemRepository; + ItemSearchRepository itemSearchRepository; @Autowired - InventoryRepository inventoryRepository; + ItemRepository itemRepository; @Autowired - ItemSearchRepository itemSearchRepository; - - @DisplayName("타입으로 구매하지 않은 아이템 목록을 조회한다.") - @Test - void find_not_purchased_items_success() { - // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); - inventoryRepository.save(inventory(memberId, morningSantaSkin)); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); - itemRepository.save(nightMageSkin()); - - // when - List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); - - // then - assertThat(actual).hasSize(1) - .containsExactly(morningKillerSkin); - } - - @DisplayName("구매하지 않은 아이템 목록은 레벨 순으로 정렬된다.") - @Test - void find_not_purchased_items_sorted_by_level_success() { - // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().unlockLevel(5).build()); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().unlockLevel(1).build()); - - // when - List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); - - // then - assertThat(actual).hasSize(2) - .containsExactly(morningKillerSkin, morningSantaSkin); - } - - @DisplayName("레벨이 같으면 가격 순으로 정렬된다.") - @Test - void find_not_purchased_items_sorted_by_price_success() { - // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().bugPrice(10).build()); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().bugPrice(20).build()); - - // when - List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); - - // then - assertThat(actual).hasSize(2) - .containsExactly(morningSantaSkin, morningKillerSkin); - } - - @DisplayName("레벨과 가격이 같으면 이름 순으로 정렬된다.") - @Test - void find_not_purchased_items_sorted_by_name_success() { - // given - Long memberId = 1L; - Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); - Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); - - // when - List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); + InventoryRepository inventoryRepository; - // then - assertThat(actual).hasSize(2) - .containsExactly(morningSantaSkin, morningKillerSkin); + @DisplayName("구매하지 않은 아이템 목록을 조회한다.") + @Nested + class FindNotPurchasedItems { + + @DisplayName("해당 타입의 구매하지 않은 아이템 목록을 조회한다.") + @Test + void success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); + inventoryRepository.save(inventory(memberId, morningSantaSkin)); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); + itemRepository.save(nightMageSkin()); + + // when + List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); + + // then + assertThat(actual).hasSize(1) + .containsExactly(morningKillerSkin); + } + + @DisplayName("구매하지 않은 아이템 목록은 레벨 순으로 정렬된다.") + @Test + void sorted_by_level_success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().unlockLevel(5).build()); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().unlockLevel(1).build()); + + // when + List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); + + // then + assertThat(actual).hasSize(2) + .containsExactly(morningKillerSkin, morningSantaSkin); + } + + @DisplayName("레벨이 같으면 가격 순으로 정렬된다.") + @Test + void sorted_by_price_success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().bugPrice(10).build()); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().bugPrice(20).build()); + + // when + List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); + + // then + assertThat(actual).hasSize(2) + .containsExactly(morningSantaSkin, morningKillerSkin); + } + + @DisplayName("레벨과 가격이 같으면 이름 순으로 정렬된다.") + @Test + void sorted_by_name_success() { + // given + Long memberId = 1L; + Item morningSantaSkin = itemRepository.save(morningSantaSkin().build()); + Item morningKillerSkin = itemRepository.save(morningKillerSkin().build()); + + // when + List actual = itemSearchRepository.findNotPurchasedItems(memberId, ItemType.MORNING); + + // then + assertThat(actual).hasSize(2) + .containsExactly(morningSantaSkin, morningKillerSkin); + } } } diff --git a/src/test/java/com/moabam/api/presentation/BugControllerTest.java b/src/test/java/com/moabam/api/presentation/BugControllerTest.java index 4bfedb04..4a78621a 100644 --- a/src/test/java/com/moabam/api/presentation/BugControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/BugControllerTest.java @@ -1,17 +1,18 @@ package com.moabam.api.presentation; +import static com.moabam.support.fixture.BugFixture.*; import static java.nio.charset.StandardCharsets.*; +import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; +import static org.springframework.http.MediaType.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import org.assertj.core.api.Assertions; 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.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; @@ -19,10 +20,8 @@ import com.moabam.api.application.BugService; import com.moabam.api.dto.BugMapper; import com.moabam.api.dto.BugResponse; -import com.moabam.fixture.BugFixture; -@SpringBootTest -@AutoConfigureMockMvc +@WebMvcTest(BugController.class) class BugControllerTest { @Autowired @@ -39,17 +38,18 @@ class BugControllerTest { void get_bug_success() throws Exception { // given Long memberId = 1L; - BugResponse expected = BugMapper.toBugResponse(BugFixture.bug()); + BugResponse expected = BugMapper.toBugResponse(bug()); given(bugService.getBug(memberId)).willReturn(expected); - // expected - String content = mockMvc.perform(get("/bugs")) + // when, then + String content = mockMvc.perform(get("/bugs") + .contentType(APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(UTF_8); BugResponse actual = objectMapper.readValue(content, BugResponse.class); - Assertions.assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(expected); } } diff --git a/src/test/java/com/moabam/api/presentation/ItemControllerTest.java b/src/test/java/com/moabam/api/presentation/ItemControllerTest.java index eee2e9a4..383a8e5b 100644 --- a/src/test/java/com/moabam/api/presentation/ItemControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/ItemControllerTest.java @@ -1,20 +1,21 @@ package com.moabam.api.presentation; +import static com.moabam.support.fixture.ItemFixture.*; import static java.nio.charset.StandardCharsets.*; import static java.util.Collections.*; +import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; +import static org.springframework.http.MediaType.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.List; -import org.assertj.core.api.Assertions; 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.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; @@ -24,10 +25,8 @@ import com.moabam.api.domain.entity.enums.ItemType; import com.moabam.api.dto.ItemMapper; import com.moabam.api.dto.ItemsResponse; -import com.moabam.fixture.ItemFixture; -@SpringBootTest -@AutoConfigureMockMvc +@WebMvcTest(ItemController.class) class ItemControllerTest { @Autowired @@ -45,20 +44,36 @@ void get_items_success() throws Exception { // given Long memberId = 1L; ItemType type = ItemType.MORNING; - Item item1 = ItemFixture.morningSantaSkin().build(); - Item item2 = ItemFixture.morningKillerSkin().build(); + Item item1 = morningSantaSkin().build(); + Item item2 = morningKillerSkin().build(); ItemsResponse expected = ItemMapper.toItemsResponse(List.of(item1, item2), emptyList()); given(itemService.getItems(memberId, type)).willReturn(expected); - // expected + // when, then String content = mockMvc.perform(get("/items") - .param("type", ItemType.MORNING.name())) + .param("type", ItemType.MORNING.name()) + .contentType(APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(UTF_8); ItemsResponse actual = objectMapper.readValue(content, ItemsResponse.class); - Assertions.assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(expected); + } + + @DisplayName("아이템을 적용한다.") + @Test + void select_item_success() throws Exception { + // given + Long memberId = 1L; + Long itemId = 1L; + + // when, then + mockMvc.perform(post("/items/{itemId}/select", itemId) + .contentType(APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()); + verify(itemService).selectItem(memberId, itemId); } } diff --git a/src/test/java/com/moabam/api/presentation/MemberControllerTest.java b/src/test/java/com/moabam/api/presentation/MemberControllerTest.java index 40a5f18d..2ecf1883 100644 --- a/src/test/java/com/moabam/api/presentation/MemberControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/MemberControllerTest.java @@ -38,10 +38,10 @@ import com.moabam.api.application.OAuth2AuthorizationServerRequestService; import com.moabam.api.dto.AuthorizationCodeResponse; import com.moabam.api.dto.AuthorizationTokenResponse; -import com.moabam.fixture.AuthorizationResponseFixture; import com.moabam.global.common.constant.GlobalConstant; import com.moabam.global.config.OAuthConfig; import com.moabam.global.error.handler.RestTemplateResponseHandler; +import com.moabam.support.fixture.AuthorizationResponseFixture; @SpringBootTest @AutoConfigureMockMvc diff --git a/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java b/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java index 5259d56c..7914b949 100644 --- a/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java @@ -27,9 +27,9 @@ import com.moabam.api.domain.repository.MemberRepository; import com.moabam.api.domain.repository.NotificationRepository; import com.moabam.api.domain.repository.RoomRepository; -import com.moabam.fixture.MemberFixture; import com.moabam.fixture.RoomFixture; import com.moabam.global.common.repository.StringRedisRepository; +import com.moabam.support.fixture.MemberFixture; @Transactional @SpringBootTest diff --git a/src/test/java/com/moabam/api/presentation/ProductControllerTest.java b/src/test/java/com/moabam/api/presentation/ProductControllerTest.java index a14c21c8..554b9b6b 100644 --- a/src/test/java/com/moabam/api/presentation/ProductControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/ProductControllerTest.java @@ -1,19 +1,20 @@ package com.moabam.api.presentation; +import static com.moabam.support.fixture.ProductFixture.*; import static java.nio.charset.StandardCharsets.*; +import static org.assertj.core.api.Assertions.*; import static org.mockito.BDDMockito.*; +import static org.springframework.http.MediaType.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.List; -import org.assertj.core.api.Assertions; 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.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; @@ -22,10 +23,8 @@ import com.moabam.api.domain.entity.Product; import com.moabam.api.dto.ProductMapper; import com.moabam.api.dto.ProductsResponse; -import com.moabam.fixture.ProductFixture; -@SpringBootTest -@AutoConfigureMockMvc +@WebMvcTest(ProductController.class) class ProductControllerTest { @Autowired @@ -41,19 +40,20 @@ class ProductControllerTest { @Test void get_products_success() throws Exception { // given - Product product1 = ProductFixture.bugProduct(); - Product product2 = ProductFixture.bugProduct(); + Product product1 = bugProduct(); + Product product2 = bugProduct(); ProductsResponse expected = ProductMapper.toProductsResponse(List.of(product1, product2)); given(productService.getProducts()).willReturn(expected); - // expected - String content = mockMvc.perform(get("/products")) + // when, then + String content = mockMvc.perform(get("/products") + .contentType(APPLICATION_JSON)) .andDo(print()) .andExpect(status().isOk()) .andReturn() .getResponse() .getContentAsString(UTF_8); ProductsResponse actual = objectMapper.readValue(content, ProductsResponse.class); - Assertions.assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(expected); } } diff --git a/src/test/java/com/moabam/api/presentation/RoomControllerTest.java b/src/test/java/com/moabam/api/presentation/RoomControllerTest.java index 06a849a6..ebcc4622 100644 --- a/src/test/java/com/moabam/api/presentation/RoomControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/RoomControllerTest.java @@ -42,8 +42,8 @@ import com.moabam.api.dto.CreateRoomRequest; import com.moabam.api.dto.EnterRoomRequest; import com.moabam.api.dto.ModifyRoomRequest; -import com.moabam.fixture.BugFixture; -import com.moabam.fixture.MemberFixture; +import com.moabam.support.fixture.BugFixture; +import com.moabam.support.fixture.MemberFixture; @Transactional @SpringBootTest diff --git a/src/test/java/com/moabam/support/annotation/QuerydslRepositoryTest.java b/src/test/java/com/moabam/support/annotation/QuerydslRepositoryTest.java new file mode 100644 index 00000000..254439c4 --- /dev/null +++ b/src/test/java/com/moabam/support/annotation/QuerydslRepositoryTest.java @@ -0,0 +1,19 @@ +package com.moabam.support.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; + +import com.moabam.support.config.TestQuerydslConfig; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(TestQuerydslConfig.class) +@DataJpaTest +public @interface QuerydslRepositoryTest { + +} diff --git a/src/test/java/com/moabam/support/config/TestQuerydslConfig.java b/src/test/java/com/moabam/support/config/TestQuerydslConfig.java new file mode 100644 index 00000000..fb7d6d8f --- /dev/null +++ b/src/test/java/com/moabam/support/config/TestQuerydslConfig.java @@ -0,0 +1,35 @@ +package com.moabam.support.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +import com.moabam.api.domain.repository.InventorySearchRepository; +import com.moabam.api.domain.repository.ItemSearchRepository; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + +@EnableJpaAuditing +@TestConfiguration +public class TestQuerydslConfig { + + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(entityManager); + } + + @Bean + public ItemSearchRepository itemSearchRepository() { + return new ItemSearchRepository(jpaQueryFactory()); + } + + @Bean + public InventorySearchRepository inventorySearchRepository() { + return new InventorySearchRepository(jpaQueryFactory()); + } +} diff --git a/src/test/java/com/moabam/fixture/AuthorizationResponseFixture.java b/src/test/java/com/moabam/support/fixture/AuthorizationResponseFixture.java similarity index 96% rename from src/test/java/com/moabam/fixture/AuthorizationResponseFixture.java rename to src/test/java/com/moabam/support/fixture/AuthorizationResponseFixture.java index 1dc1f3d6..c1671fb7 100644 --- a/src/test/java/com/moabam/fixture/AuthorizationResponseFixture.java +++ b/src/test/java/com/moabam/support/fixture/AuthorizationResponseFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.dto.AuthorizationCodeResponse; import com.moabam.api.dto.AuthorizationTokenInfoResponse; diff --git a/src/test/java/com/moabam/fixture/BugFixture.java b/src/test/java/com/moabam/support/fixture/BugFixture.java similarity index 90% rename from src/test/java/com/moabam/fixture/BugFixture.java rename to src/test/java/com/moabam/support/fixture/BugFixture.java index 8d2b8703..91eb772e 100644 --- a/src/test/java/com/moabam/fixture/BugFixture.java +++ b/src/test/java/com/moabam/support/fixture/BugFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.domain.entity.Bug; diff --git a/src/test/java/com/moabam/fixture/InventoryFixture.java b/src/test/java/com/moabam/support/fixture/InventoryFixture.java similarity index 88% rename from src/test/java/com/moabam/fixture/InventoryFixture.java rename to src/test/java/com/moabam/support/fixture/InventoryFixture.java index 357443dc..9c060c20 100644 --- a/src/test/java/com/moabam/fixture/InventoryFixture.java +++ b/src/test/java/com/moabam/support/fixture/InventoryFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.domain.entity.Inventory; import com.moabam.api.domain.entity.Item; diff --git a/src/test/java/com/moabam/fixture/ItemFixture.java b/src/test/java/com/moabam/support/fixture/ItemFixture.java similarity index 97% rename from src/test/java/com/moabam/fixture/ItemFixture.java rename to src/test/java/com/moabam/support/fixture/ItemFixture.java index 3d95487f..73fb9e78 100644 --- a/src/test/java/com/moabam/fixture/ItemFixture.java +++ b/src/test/java/com/moabam/support/fixture/ItemFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.domain.entity.Item; import com.moabam.api.domain.entity.enums.ItemCategory; diff --git a/src/test/java/com/moabam/fixture/MemberFixture.java b/src/test/java/com/moabam/support/fixture/MemberFixture.java similarity index 94% rename from src/test/java/com/moabam/fixture/MemberFixture.java rename to src/test/java/com/moabam/support/fixture/MemberFixture.java index d8f424c1..80bb1b03 100644 --- a/src/test/java/com/moabam/fixture/MemberFixture.java +++ b/src/test/java/com/moabam/support/fixture/MemberFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.domain.entity.Member; diff --git a/src/test/java/com/moabam/fixture/ProductFixture.java b/src/test/java/com/moabam/support/fixture/ProductFixture.java similarity index 93% rename from src/test/java/com/moabam/fixture/ProductFixture.java rename to src/test/java/com/moabam/support/fixture/ProductFixture.java index 91170206..e8b2b3fd 100644 --- a/src/test/java/com/moabam/fixture/ProductFixture.java +++ b/src/test/java/com/moabam/support/fixture/ProductFixture.java @@ -1,4 +1,4 @@ -package com.moabam.fixture; +package com.moabam.support.fixture; import com.moabam.api.domain.entity.Product; import com.moabam.api.domain.entity.enums.ProductType;