Write first unit tests for PlayerListener

This commit is contained in:
ljacqu 2016-08-03 22:11:48 +02:00
parent 4aad1d506c
commit bb52e0120c
3 changed files with 216 additions and 1 deletions

View File

@ -210,7 +210,7 @@ public class PlayerListener implements Listener {
public void onPlayerLogin(PlayerLoginEvent event) { public void onPlayerLogin(PlayerLoginEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final String name = player.getName(); final String name = player.getName();
if (validationService.isUnrestricted(player.getName())) { if (validationService.isUnrestricted(name)) {
return; return;
} else if (onJoinVerifier.refusePlayerForFullServer(event)) { } else if (onJoinVerifier.refusePlayerForFullServer(event)) {
return; return;

View File

@ -0,0 +1,71 @@
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 static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Utilities for testing AuthMe listener classes.
*/
public final class ListenerTestUtils {
private ListenerTestUtils() {
}
public static <T extends Event & Cancellable>
void checkEventIsCanceledForUnauthed(Listener listener, ListenerService listenerService, Class<T> clazz) {
Method handlerMethod = findMethod(listener, clazz);
T event = mock(clazz);
mockShouldCancel(true, listenerService, event);
ReflectionTestUtils.invokeMethod(handlerMethod, listener, event);
verify(event).setCancelled(true);
event = mock(clazz);
mockShouldCancel(false, listenerService, event);
ReflectionTestUtils.invokeMethod(handlerMethod, listener, event);
verifyZeroInteractions(event);
}
private static void mockShouldCancel(boolean result, ListenerService listenerService, Event event) {
if (event instanceof PlayerEvent) {
given(listenerService.shouldCancelEvent((PlayerEvent) event)).willReturn(result);
} else if (event instanceof EntityEvent) {
given(listenerService.shouldCancelEvent((EntityEvent) event)).willReturn(result);
} else {
throw new IllegalStateException("Found event with unsupported type: " + event.getClass());
}
}
private static <T> Method findMethod(Listener listener, Class<T> 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;
}
}

View File

@ -0,0 +1,144 @@
package fr.xephi.authme.listener;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.TeleportationService;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static fr.xephi.authme.listener.ListenerTestUtils.checkEventIsCanceledForUnauthed;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Test for {@link PlayerListener}.
*/
@RunWith(MockitoJUnitRunner.class)
public class PlayerListenerTest {
@InjectMocks
private PlayerListener listener;
@Mock
private Settings settings;
@Mock
private Messages m;
@Mock
private DataSource dataSource;
@Mock
private AntiBot antiBot;
@Mock
private Management management;
@Mock
private BukkitService bukkitService;
@Mock
private SpawnLoader spawnLoader;
@Mock
private OnJoinVerifier onJoinVerifier;
@Mock
private ListenerService listenerService;
@Mock
private TeleportationService teleportationService;
@Mock
private ValidationService validationService;
/**
* #831: If a player is kicked because of "logged in from another location", the kick
* should be CANCELED when single session is enabled.
*/
@Test
public void shouldCancelKick() {
// given
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true);
Player player = mock(Player.class);
PlayerKickEvent event = new PlayerKickEvent(player, "You logged in from another location", "");
// when
listener.onPlayerKick(event);
// then
assertThat(event.isCancelled(), equalTo(true));
verifyZeroInteractions(player, management, antiBot);
}
@Test
public void shouldNotCancelKick() {
// given
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(false);
String name = "Bobby";
Player player = mockPlayerWithName(name);
PlayerKickEvent event = new PlayerKickEvent(player, "You logged in from another location", "");
given(antiBot.wasPlayerKicked(name)).willReturn(false);
// when
listener.onPlayerKick(event);
// then
assertThat(event.isCancelled(), equalTo(false));
verify(antiBot).wasPlayerKicked(name);
verify(management).performQuit(player);
}
@Test
public void shouldNotCancelOrdinaryKick() {
// given
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true);
String name = "Bobby";
Player player = mockPlayerWithName(name);
PlayerKickEvent event = new PlayerKickEvent(player, "No longer desired here!", "");
given(antiBot.wasPlayerKicked(name)).willReturn(true);
// when
listener.onPlayerKick(event);
// then
assertThat(event.isCancelled(), equalTo(false));
verify(antiBot).wasPlayerKicked(name);
verifyZeroInteractions(management);
}
@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);
}
private static Player mockPlayerWithName(String name) {
Player player = mock(Player.class);
given(player.getName()).willReturn(name);
return player;
}
}