From 252813197fb176dfb128e782535f80966302bc12 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 16 Oct 2016 11:19:54 +0200 Subject: [PATCH] Test simple event cancellation with method references instead of reflection --- .../authme/listener/EntityListenerTest.java | 67 ++------------- ...estUtils.java => EventCancelVerifier.java} | 70 ++++++--------- .../authme/listener/PlayerListener16Test.java | 5 +- .../authme/listener/PlayerListener18Test.java | 5 +- .../authme/listener/PlayerListener19Test.java | 5 +- .../authme/listener/PlayerListenerTest.java | 29 ++++--- .../authme/listener/ServerListenerTest.java | 85 +++---------------- 7 files changed, 72 insertions(+), 194 deletions(-) rename src/test/java/fr/xephi/authme/listener/{ListenerTestUtils.java => EventCancelVerifier.java} (51%) diff --git a/src/test/java/fr/xephi/authme/listener/EntityListenerTest.java b/src/test/java/fr/xephi/authme/listener/EntityListenerTest.java index 0b7b00845..1f36fa8d4 100644 --- a/src/test/java/fr/xephi/authme/listener/EntityListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/EntityListenerTest.java @@ -18,7 +18,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import static fr.xephi.authme.listener.ListenerTestUtils.checkEventIsCanceledForUnauthed; +import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Mockito.mock; @@ -41,65 +41,12 @@ public class EntityListenerTest { @Test public void shouldHandleSimpleEvents() { - checkEventIsCanceledForUnauthed(listener, listenerService, EntityTargetEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, FoodLevelChangeEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, EntityShootBowEvent.class); - } - - @Test - public void shouldCancelEntityInteractEvent() { - // given - EntityInteractEvent event = mock(EntityInteractEvent.class); - given(listenerService.shouldCancelEvent(event)).willReturn(true); - - // when - listener.onLowestEntityInteract(event); - - // then - verify(listenerService).shouldCancelEvent(event); - verify(event).setCancelled(true); - } - - @Test - public void shouldNotCancelEntityInteractEvent() { - // given - EntityInteractEvent event = mock(EntityInteractEvent.class); - given(listenerService.shouldCancelEvent(event)).willReturn(false); - - // when - listener.onLowestEntityInteract(event); - - // then - verify(listenerService).shouldCancelEvent(event); - verifyZeroInteractions(event); - } - - @Test - public void shouldCancelEntityInteractEventHighest() { - // given - EntityInteractEvent event = mock(EntityInteractEvent.class); - given(listenerService.shouldCancelEvent(event)).willReturn(true); - - // when - listener.onEntityInteract(event); - - // then - verify(listenerService).shouldCancelEvent(event); - verify(event).setCancelled(true); - } - - @Test - public void shouldNotCancelEntityInteractEventHighest() { - // given - EntityInteractEvent event = mock(EntityInteractEvent.class); - given(listenerService.shouldCancelEvent(event)).willReturn(false); - - // when - listener.onEntityInteract(event); - - // then - verify(listenerService).shouldCancelEvent(event); - verifyZeroInteractions(event); + withServiceMock(listenerService) + .check(listener::onEntityTarget, EntityTargetEvent.class) + .check(listener::onFoodLevelChange, FoodLevelChangeEvent.class) + .check(listener::onShoot, EntityShootBowEvent.class) + .check(listener::onEntityInteract, EntityInteractEvent.class) + .check(listener::onLowestEntityInteract, EntityInteractEvent.class); } @Test diff --git a/src/test/java/fr/xephi/authme/listener/ListenerTestUtils.java b/src/test/java/fr/xephi/authme/listener/EventCancelVerifier.java similarity index 51% rename from src/test/java/fr/xephi/authme/listener/ListenerTestUtils.java rename to src/test/java/fr/xephi/authme/listener/EventCancelVerifier.java index cdc07cce8..f74dc24bd 100644 --- a/src/test/java/fr/xephi/authme/listener/ListenerTestUtils.java +++ b/src/test/java/fr/xephi/authme/listener/EventCancelVerifier.java @@ -1,14 +1,11 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.ReflectionTestUtils; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityEvent; import org.bukkit.event.player.PlayerEvent; -import java.lang.reflect.Method; +import java.util.function.Consumer; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -16,11 +13,25 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; /** - * Utilities for testing AuthMe listener classes. + * Tests simple listener methods that should cancel an event when the listener service says so. */ -public final class ListenerTestUtils { +public final class EventCancelVerifier { - private ListenerTestUtils() { + private final ListenerService listenerService; + + private EventCancelVerifier(ListenerService listenerService) { + this.listenerService = listenerService; + } + + /** + * Creates a new verifier that uses the given ListenerService mock (needs to be the same instance + * as used in the listener class to test). + * + * @param listenerService the listener service mock + * @return new verifier + */ + public static EventCancelVerifier withServiceMock(ListenerService listenerService) { + return new EventCancelVerifier(listenerService); } /** @@ -29,25 +40,23 @@ public final class ListenerTestUtils { * canceled when the service says so and the other way around. Do not use this * method if the handler method has additional behavior. * - * - * @param listener the listener to test - * @param listenerService the listener service mock + * @param listenerMethod the listener method to test * @param clazz the event class to test the handler method for * @param the event type + * @return the verifier (for chaining of methods) */ - public static - void checkEventIsCanceledForUnauthed(Listener listener, ListenerService listenerService, Class clazz) { - Method handlerMethod = findMethod(listener, clazz); - + public EventCancelVerifier check(Consumer listenerMethod, Class clazz) { T event = mock(clazz); mockShouldCancel(true, listenerService, event); - ReflectionTestUtils.invokeMethod(handlerMethod, listener, event); + listenerMethod.accept(event); verify(event).setCancelled(true); event = mock(clazz); mockShouldCancel(false, listenerService, event); - ReflectionTestUtils.invokeMethod(handlerMethod, listener, event); + listenerMethod.accept(event); verifyZeroInteractions(event); + + return this; } /** @@ -67,33 +76,4 @@ public final class ListenerTestUtils { throw new IllegalStateException("Found event with unsupported type: " + event.getClass()); } } - - /** - * Returns the method in the listener that takes the given event type as parameter. - * - * @param listener the listener to scan - * @param paramType the event type - * @return the mapped method - * @throws IllegalStateException if there is not exactly one method with the given event type as parameter - */ - private static Method findMethod(Listener listener, Class paramType) { - Method matchingMethod = null; - for (Method method : listener.getClass().getMethods()) { - if (method.isAnnotationPresent(EventHandler.class)) { - Class[] parameters = method.getParameterTypes(); - if (parameters.length == 1 && parameters[0] == paramType) { - if (matchingMethod == null) { - matchingMethod = method; - } else { - throw new IllegalStateException("Found multiple eligible methods for " + paramType); - } - } - } - } - if (matchingMethod == null) { - throw new IllegalStateException("Found no matching method for " + paramType); - } - return matchingMethod; - } - } diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListener16Test.java b/src/test/java/fr/xephi/authme/listener/PlayerListener16Test.java index 980f9dabb..c60b8abff 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListener16Test.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListener16Test.java @@ -7,6 +7,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock; + /** * Test for {@link PlayerListener16}. */ @@ -21,7 +23,8 @@ public class PlayerListener16Test { @Test public void shouldCancelEvent() { - ListenerTestUtils.checkEventIsCanceledForUnauthed(listener, listenerService, PlayerEditBookEvent.class); + withServiceMock(listenerService) + .check(listener::onPlayerEditBook, PlayerEditBookEvent.class); } } diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListener18Test.java b/src/test/java/fr/xephi/authme/listener/PlayerListener18Test.java index 79466a31d..9b93a270b 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListener18Test.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListener18Test.java @@ -7,6 +7,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock; + /** * Test for {@link PlayerListener18}. */ @@ -21,7 +23,8 @@ public class PlayerListener18Test { @Test public void shouldCancelEvent() { - ListenerTestUtils.checkEventIsCanceledForUnauthed(listener, listenerService, PlayerInteractAtEntityEvent.class); + withServiceMock(listenerService) + .check(listener::onPlayerInteractAtEntity, PlayerInteractAtEntityEvent.class); } } diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListener19Test.java b/src/test/java/fr/xephi/authme/listener/PlayerListener19Test.java index 8fcd39b68..50dd179dc 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListener19Test.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListener19Test.java @@ -7,6 +7,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock; + /** * Test for {@link PlayerListener19}. */ @@ -21,7 +23,8 @@ public class PlayerListener19Test { @Test public void shouldCancelEvent() { - ListenerTestUtils.checkEventIsCanceledForUnauthed(listener, listenerService, PlayerSwapHandItemsEvent.class); + withServiceMock(listenerService) + .check(listener::onPlayerSwapHandItems, PlayerSwapHandItemsEvent.class); } } diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java index 74f9d5083..15bf4c6ee 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java @@ -1,18 +1,18 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.service.AntiBotService; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.message.Messages; import fr.xephi.authme.process.Management; +import fr.xephi.authme.service.AntiBotService; +import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.service.TeleportationService; +import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; -import fr.xephi.authme.service.BukkitService; -import fr.xephi.authme.service.TeleportationService; -import fr.xephi.authme.service.ValidationService; import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.World; @@ -45,7 +45,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import static fr.xephi.authme.listener.ListenerTestUtils.checkEventIsCanceledForUnauthed; +import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; @@ -153,15 +153,16 @@ public class PlayerListenerTest { @Test public void shouldHandleSimpleCancelableEvents() { - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerShearEntityEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerFishEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerBedEnterEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerDropItemEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, EntityDamageByEntityEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerItemConsumeEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerInteractEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerPickupItemEvent.class); - checkEventIsCanceledForUnauthed(listener, listenerService, PlayerInteractEntityEvent.class); + withServiceMock(listenerService) + .check(listener::onPlayerShear, PlayerShearEntityEvent.class) + .check(listener::onPlayerFish, PlayerFishEvent.class) + .check(listener::onPlayerBedEnter, PlayerBedEnterEvent.class) + .check(listener::onPlayerDropItem, PlayerDropItemEvent.class) + .check(listener::onPlayerHitPlayerEvent, EntityDamageByEntityEvent.class) + .check(listener::onPlayerConsumeItem, PlayerItemConsumeEvent.class) + .check(listener::onPlayerInteract, PlayerInteractEvent.class) + .check(listener::onPlayerPickupItem, PlayerPickupItemEvent.class) + .check(listener::onPlayerInteractEntity, PlayerInteractEntityEvent.class); } @Test diff --git a/src/test/java/fr/xephi/authme/listener/ServerListenerTest.java b/src/test/java/fr/xephi/authme/listener/ServerListenerTest.java index 266a437ff..d40683c37 100644 --- a/src/test/java/fr/xephi/authme/listener/ServerListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/ServerListenerTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; /** * Test for {@link ServerListener}. @@ -56,82 +57,22 @@ public class ServerListenerTest { @Test public void shouldForwardPluginNameOnEnable() { - checkEnableHandling(ESSENTIALS, new Runnable() { - @Override - public void run() { - verify(pluginHookService).tryHookToEssentials(); - } - }); - checkEnableHandling(ESSENTIALS_SPAWN, new Runnable() { - @Override - public void run() { - verify(spawnLoader).loadEssentialsSpawn(); - } - }); - checkEnableHandling(MULTIVERSE, new Runnable() { - @Override - public void run() { - verify(pluginHookService).tryHookToMultiverse(); - } - }); - checkEnableHandling(COMBAT_TAG, new Runnable() { - @Override - public void run() { - verify(pluginHookService).tryHookToCombatPlus(); - } - }); - checkEnableHandling(PROTOCOL_LIB, new Runnable() { - @Override - public void run() { - verify(protocolLibService).setup(); - } - }); - checkEnableHandling("UnknownPlugin", new Runnable() { - @Override - public void run() { - // nothing - } - }); + checkEnableHandling(ESSENTIALS, () -> verify(pluginHookService).tryHookToEssentials()); + checkEnableHandling(ESSENTIALS_SPAWN, () -> verify(spawnLoader).loadEssentialsSpawn()); + checkEnableHandling(MULTIVERSE, () -> verify(pluginHookService).tryHookToMultiverse()); + checkEnableHandling(COMBAT_TAG, () -> verify(pluginHookService).tryHookToCombatPlus()); + checkEnableHandling(PROTOCOL_LIB, () -> verify(protocolLibService).setup()); + checkEnableHandling("UnknownPlugin", () -> verifyZeroInteractions(pluginHookService, spawnLoader)); } @Test public void shouldForwardPluginNameOnDisable() { - checkDisableHandling(ESSENTIALS, new Runnable() { - @Override - public void run() { - verify(pluginHookService).unhookEssentials(); - } - }); - checkDisableHandling(ESSENTIALS_SPAWN, new Runnable() { - @Override - public void run() { - verify(spawnLoader).unloadEssentialsSpawn(); - } - }); - checkDisableHandling(MULTIVERSE, new Runnable() { - @Override - public void run() { - verify(pluginHookService).unhookMultiverse(); - } - }); - checkDisableHandling(COMBAT_TAG, new Runnable() { - @Override - public void run() { - verify(pluginHookService).unhookCombatPlus(); - } - }); - checkDisableHandling(PROTOCOL_LIB, new Runnable() { - @Override - public void run() { - verify(protocolLibService).disable(); - } - }); - checkDisableHandling("UnknownPlugin", new Runnable() { - @Override - public void run() { - // nothing - } - }); + checkDisableHandling(ESSENTIALS, () -> verify(pluginHookService).unhookEssentials()); + checkDisableHandling(ESSENTIALS_SPAWN, () -> verify(spawnLoader).unloadEssentialsSpawn()); + checkDisableHandling(MULTIVERSE, () -> verify(pluginHookService).unhookMultiverse()); + checkDisableHandling(COMBAT_TAG, () -> verify(pluginHookService).unhookCombatPlus()); + checkDisableHandling(PROTOCOL_LIB, () -> verify(protocolLibService).disable()); + checkDisableHandling("UnknownPlugin", () -> verifyZeroInteractions(pluginHookService, spawnLoader)); } @Test