From 6640f2ba63e5a7512202be8e09889535932e1740 Mon Sep 17 00:00:00 2001 From: Jackson Bailey Date: Sun, 30 Jun 2024 21:52:26 -0400 Subject: [PATCH] Add more tests for AbstractCommand --- .../jacksonbailey/wheel/terra/TestUtils.java | 13 +++ .../terra/service/AbstractCommandTest.java | 98 ++++++++++++++++--- 2 files changed, 99 insertions(+), 12 deletions(-) diff --git a/terra/src/test/java/dev/jacksonbailey/wheel/terra/TestUtils.java b/terra/src/test/java/dev/jacksonbailey/wheel/terra/TestUtils.java index 71af006..7a09bed 100644 --- a/terra/src/test/java/dev/jacksonbailey/wheel/terra/TestUtils.java +++ b/terra/src/test/java/dev/jacksonbailey/wheel/terra/TestUtils.java @@ -1,7 +1,9 @@ package dev.jacksonbailey.wheel.terra; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; +import java.util.concurrent.Future; import java.util.function.Consumer; public final class TestUtils { @@ -16,5 +18,16 @@ public static Consumer anyConsumerOf(T t) { return toReturn; } + public static Consumer nullableConsumerOf(T t) { + @SuppressWarnings("unchecked") + Consumer toReturn = nullable(Consumer.class); + return toReturn; + } + + public static Future anyFutureOf(T t) { + @SuppressWarnings("unchecked") + Future toReturn = any(Future.class); + return toReturn; + } } diff --git a/terra/src/test/java/dev/jacksonbailey/wheel/terra/service/AbstractCommandTest.java b/terra/src/test/java/dev/jacksonbailey/wheel/terra/service/AbstractCommandTest.java index 2c77d9f..c3cddd1 100644 --- a/terra/src/test/java/dev/jacksonbailey/wheel/terra/service/AbstractCommandTest.java +++ b/terra/src/test/java/dev/jacksonbailey/wheel/terra/service/AbstractCommandTest.java @@ -1,22 +1,36 @@ package dev.jacksonbailey.wheel.terra.service; import static dev.jacksonbailey.wheel.terra.TestUtils.anyConsumerOf; +import static dev.jacksonbailey.wheel.terra.TestUtils.nullableConsumerOf; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.function.Consumer; import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.interactions.InteractionHook; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -31,7 +45,7 @@ class AbstractCommandTest { private JDA jda; @InjectMocks - private AbstractCommandStub abstractCommandStub; + private AbstractCommandStub commandStub; @Mock RestAction upsertRestAction; @@ -77,23 +91,83 @@ protected Consumer onUpsertCommandFailure() { } } - @BeforeEach - void beforeEach() { + @Test + void registerCommand_addsListener() { given(jda.upsertCommand(any(CommandData.class))).willReturn(upsertRestAction); - } - @Test - void registerCommandAddsListener() { - abstractCommandStub.registerCommand(); - verify(jda).addEventListener(abstractCommandStub); + commandStub.registerCommand(); + + verify(jda).addEventListener(commandStub); } @Test - void registerCommandUpsertsCommand() { - abstractCommandStub.registerCommand(); + void registerCommand_upsertsCommand() { + given(jda.upsertCommand(any(CommandData.class))).willReturn(upsertRestAction); + + commandStub.registerCommand(); + verify(jda).upsertCommand(commandData); verify(upsertRestAction).queue(anyConsumerOf(Command.class), eq(upsertCommandFailure)); } - // TODO Add more unit tests + @Test + void onSlashCommand_doesNotTriggersOnWrongCommand() { + var event = mock(SlashCommandInteractionEvent.class); + given(event.getName()).willReturn(UUID.randomUUID().toString()); + + commandStub.onSlashCommandInteraction(event); + + verify(event).getName(); + verifyNoMoreInteractions(event); + } + + @Test + void onSlashCommand_defersReply() { + var event = mock(SlashCommandInteractionEvent.class); + var callback = mock(ReplyCallbackAction.class); + given(event.getName()).willReturn(commandStub.getCommandName()); + given(event.deferReply(anyBoolean())).willReturn(callback); + + commandStub.onSlashCommandInteraction(event); + + verify(event).getName(); + verify(event).deferReply(commandStub.isEphemeral()); + verify(callback).queue(anyConsumerOf(InteractionHook.class), + nullableConsumerOf(Throwable.class)); + } + + @ParameterizedTest + @ValueSource(classes = {ExecutionException.class, InterruptedException.class}) + void onDeferReplySuccess_throwsWhenMessageFutureFails(Class thrown) + throws Exception { + InteractionHook hook = mock(InteractionHook.class); + Throwable thrownByMessageFuture = mock(thrown); + @SuppressWarnings("unchecked") + Future messageFuture = mock(Future.class); + given(messageFuture.get()).willThrow(thrownByMessageFuture); + + var actualException = assertThrows(RuntimeException.class, + () -> commandStub.onDeferReplySuccess(hook, messageFuture)); + + assertThat(actualException).cause().isSameAs(thrownByMessageFuture); + } + + @Test + void onDeferReplySuccess_hookIsCalled() throws Exception { + @SuppressWarnings("unchecked") + Future messageFuture = mock(Future.class); + var messageCreateData = mock(MessageCreateData.class); + given(messageFuture.get()).willReturn(messageCreateData); + + var hook = mock(InteractionHook.class); + @SuppressWarnings("unchecked") + WebhookMessageCreateAction callback = mock(WebhookMessageCreateAction.class); + given(hook.sendMessage(messageCreateData)).willReturn(callback); + + commandStub.onDeferReplySuccess(hook, messageFuture); + + verify(hook).sendMessage(messageCreateData); + verify(callback).queue(anyConsumerOf(Message.class), nullableConsumerOf(Throwable.class)); + } + }