diff --git a/character/build.gradle b/character/build.gradle index a03c4fe..a96bf4d 100644 --- a/character/build.gradle +++ b/character/build.gradle @@ -11,6 +11,7 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'io.r2dbc:r2dbc-h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'io.projectreactor:reactor-test' implementation project(':item'); implementation project(':inventory') diff --git a/character/src/main/java/com/developer/domainmodel/CharacterDomain.java b/character/src/main/java/com/developer/domainmodel/CharacterDomain.java new file mode 100644 index 0000000..761ea69 --- /dev/null +++ b/character/src/main/java/com/developer/domainmodel/CharacterDomain.java @@ -0,0 +1,32 @@ +package com.developer.domainmodel; + + +import java.util.UUID; + +public record CharacterDomain( + UUID id, + int backend, + int frontend, + int ops, + int health, + int teamwork + ) { + public CharacterDomain(UUID id){ + this(id,0,0,0 ,0,0); + } + public CharacterDomain withBackend(int backend) { + return new CharacterDomain(this.id, backend, this.frontend, this.ops, this.health, this.teamwork); + } + public CharacterDomain withFrontend(int frontend) { + return new CharacterDomain(this.id, this.backend, frontend, this.ops, this.health, this.teamwork); + } + public CharacterDomain withOps(int ops) { + return new CharacterDomain(this.id, this.backend, this.frontend, ops, this.health, this.teamwork); + } + public CharacterDomain withHealth(int health) { + return new CharacterDomain(this.id, this.backend, this.frontend, this.ops, health, this.teamwork); + } + public CharacterDomain withTeamwork(int teamwork) { + return new CharacterDomain(this.id, this.backend, this.frontend, this.ops, this.health, teamwork); + } +} diff --git a/character/src/main/java/com/developer/processor/CharacterStatProcessor.java b/character/src/main/java/com/developer/processor/CharacterStatProcessor.java index a83fddf..bb051c1 100644 --- a/character/src/main/java/com/developer/processor/CharacterStatProcessor.java +++ b/character/src/main/java/com/developer/processor/CharacterStatProcessor.java @@ -1,5 +1,9 @@ package com.developer.processor; +import com.developer.domainmodel.CharacterDomain; +import reactor.core.publisher.Mono; + + public interface CharacterStatProcessor { - void updateStat(int point); + Mono updateStat(CharacterDomain character, String targetStat, int point); } diff --git a/character/src/main/java/com/developer/processor/CharacterStatProcessorImpl.java b/character/src/main/java/com/developer/processor/CharacterStatProcessorImpl.java index f0617d3..0f87d9c 100644 --- a/character/src/main/java/com/developer/processor/CharacterStatProcessorImpl.java +++ b/character/src/main/java/com/developer/processor/CharacterStatProcessorImpl.java @@ -1,9 +1,20 @@ package com.developer.processor; +import com.developer.domainmodel.CharacterDomain; +import reactor.core.publisher.Mono; + public class CharacterStatProcessorImpl implements CharacterStatProcessor{ @Override - public void updateStat(int point) { - + public Mono updateStat(CharacterDomain character, String targetStat, int point) { + return Mono.just(character) + .map(c -> switch (targetStat) { + case "backend" -> c.withBackend(c.backend() + point); + case "frontend" -> c.withFrontend(c.frontend() + point); + case "ops" -> c.withOps(c.ops() + point); + case "health" -> c.withHealth(c.health() + point); + case "teamwork" -> c.withTeamwork(c.teamwork() + point); + default -> throw new IllegalArgumentException(targetStat + " Is Not Support Stat"); + }); } } diff --git a/character/src/main/java/com/developer/service/CharacterServiceImpl.java b/character/src/main/java/com/developer/service/CharacterServiceImpl.java index 7e80464..1697dc5 100644 --- a/character/src/main/java/com/developer/service/CharacterServiceImpl.java +++ b/character/src/main/java/com/developer/service/CharacterServiceImpl.java @@ -1,10 +1,13 @@ package com.developer.service; +import com.developer.domainmodel.CharacterDomain; import com.developer.processor.BookFindProcessor; import com.developer.processor.CharacterStatProcessor; import com.developer.processor.InventoryBookProcessor; import reactor.core.publisher.Mono; +import java.util.UUID; + public class CharacterServiceImpl implements CharacterService{ private final CharacterStatProcessor characterStatProcessor; @@ -23,7 +26,7 @@ public CharacterServiceImpl(CharacterStatProcessor characterStatProcessor, BookF public Mono readBook(String characterUUID, String bookUUID) { inventoryBookProcessor.checkBook(characterUUID, bookUUID); bookFindProcessor.getBook(bookUUID); - characterStatProcessor.updateStat(1); + characterStatProcessor.updateStat(new CharacterDomain(UUID.randomUUID()),"backend", 3); inventoryBookProcessor.consumeBook(characterUUID, bookUUID); return Mono.just(Boolean.TRUE); } diff --git a/character/src/test/java/com/developer/processor/CharacterStatProcessorTests.java b/character/src/test/java/com/developer/processor/CharacterStatProcessorTests.java new file mode 100644 index 0000000..b4f0989 --- /dev/null +++ b/character/src/test/java/com/developer/processor/CharacterStatProcessorTests.java @@ -0,0 +1,41 @@ +package com.developer.processor; + +import com.developer.domainmodel.CharacterDomain; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Stream; + +public class CharacterStatProcessorTests { + + private CharacterStatProcessor processor; + + @TestFactory + Stream updateStatTests() { + processor = new CharacterStatProcessorImpl(); + List> values = List.of( + List.of(new CharacterDomain(UUID.fromString("11b9649d-0ae3-4175-bf1f-abcfb1047100")), "backend", 10, + new CharacterDomain(UUID.fromString("11b9649d-0ae3-4175-bf1f-abcfb1047100"),10,0,0,0,0)), + List.of(new CharacterDomain(UUID.fromString("21b9649d-0ae3-4175-bf1f-abcfb1047100")), "frontend", 7, + new CharacterDomain(UUID.fromString("21b9649d-0ae3-4175-bf1f-abcfb1047100"),0,7,0,0,0)), + List.of(new CharacterDomain(UUID.fromString("31b9649d-0ae3-4175-bf1f-abcfb1047100")), "ops", 3, + new CharacterDomain(UUID.fromString("31b9649d-0ae3-4175-bf1f-abcfb1047100"),0,0,3,0,0)), + List.of(new CharacterDomain(UUID.fromString("41b9649d-0ae3-4175-bf1f-abcfb1047100")), "health", -5, + new CharacterDomain(UUID.fromString("41b9649d-0ae3-4175-bf1f-abcfb1047100"),0,0,0,-5,0)), + List.of(new CharacterDomain(UUID.fromString("51b9649d-0ae3-4175-bf1f-abcfb1047100")), "teamwork", -3, + new CharacterDomain(UUID.fromString("51b9649d-0ae3-4175-bf1f-abcfb1047100"),0,0,0,0,-3)) + ); + return values.stream().map(value -> + DynamicTest.dynamicTest("CASE: 캐릭터의 특정 스텟을 업데이트한다.", () -> { + Mono result = processor.updateStat((CharacterDomain)value.get(0),(String)value.get(1), (int)value.get(2)); + StepVerifier.create(result) + .expectNext((CharacterDomain) value.get(3)) + .verifyComplete(); + }) + ); + } +} diff --git a/character/src/test/java/com/developer/service/CharacterServiceTest.java b/character/src/test/java/com/developer/service/CharacterServiceTest.java index ca680d5..f995d67 100644 --- a/character/src/test/java/com/developer/service/CharacterServiceTest.java +++ b/character/src/test/java/com/developer/service/CharacterServiceTest.java @@ -1,5 +1,6 @@ package com.developer.service; +import com.developer.domainmodel.CharacterDomain; import com.developer.processor.BookFindProcessorImpl; import com.developer.processor.CharacterStatProcessorImpl; import com.developer.processor.InventoryBookProcessorImpl; @@ -11,6 +12,8 @@ import org.mockito.junit.jupiter.MockitoExtension; import reactor.core.publisher.Mono; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.then; @@ -53,7 +56,7 @@ void readBookTest() { then(inventoryBookProcessor).should(times(1)).checkBook(anyString(), anyString()); then(bookFindProcessor).should(times(1)).getBook(anyString()); then(inventoryBookProcessor).should(times(1)).consumeBook(anyString(), anyString()); - then(characterStatProcessor).should(times(1)).updateStat(anyInt()); + then(characterStatProcessor).should(times(1)).updateStat(new CharacterDomain(UUID.randomUUID()), "backend", 3); assertThat(result).isInstanceOf(Mono.class); // todo: Mono 검증방법 구상 : chatGPT의 구상은 해당 두줄로 구성 assertThat(result.block()).isInstanceOf(Boolean.class);