Skip to content

Commit

Permalink
Unit tests for DamageSourceMock (#973)
Browse files Browse the repository at this point in the history
* Added unimplemented methods

* Added unit tests for DamageSourceMock

* Removed unnecessary annotation

* Added new constructor and deprecated old

* Refactored unit tests to use new constructor

* Added unit test for DamageTypeMock.from

* Re-trigger failed build

* Fixed javadoc

* Replaced usage of "var" with real types

* Improved test class readability

---------

Co-authored-by: Thorinwasher <37477983+Thorinwasher@users.noreply.github.com>
  • Loading branch information
4everTheOne and Thorinwasher committed Feb 22, 2024
1 parent b9b7e32 commit adc2d6d
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/main/java/be/seeseemelk/mockbukkit/RegistryMock.java
Expand Up @@ -118,7 +118,7 @@ else if (tClass == PotionEffectType.class)
}
else if (tClass == DamageType.class)
{
return DamageTypeMock::new;
return DamageTypeMock::from;
}
else
{
Expand Down
Expand Up @@ -56,7 +56,7 @@ public DamageSourceMock(DamageType damageType, Entity causingEntity, Entity dire
{
if (this.damageLocation != null)
{
return this.damageLocation;
return getDamageLocation();
}
return this.directEntity != null ? this.directEntity.getLocation() : null;
}
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/be/seeseemelk/mockbukkit/damage/DamageTypeMock.java
@@ -1,6 +1,7 @@
package be.seeseemelk.mockbukkit.damage;

import be.seeseemelk.mockbukkit.UnimplementedOperationException;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
Expand All @@ -13,13 +14,81 @@

public class DamageTypeMock implements DamageType
{
static final String EXHAUSTION = "exhaustion";
static final String DEATH_MESSAGE_TYPE = "deathMessageType";
static final String SOUND = "sound";
static final String DAMAGE_SCALING = "damageScaling";
static final String KEY = "key";

/**
* Create a {@link DamageTypeMock} from a {@link JsonObject}.
* <p>
* Example:
* <pre>
* {
* "key": "minecraft:in_fire",
* "damageScaling": "WHEN_CAUSED_BY_LIVING_NON_PLAYER",
* "sound": "minecraft:entity.player.hurt_on_fire",
* "deathMessageType": "DEFAULT",
* "exhaustion": 0.1
* }
* </pre>
*
* @param data The json data.
*
* @return The damage type created from the JSON
*/
public static DamageTypeMock from(JsonObject data)
{
Preconditions.checkArgument(data != null, "JsonObject can't be null");
Preconditions.checkArgument(data.has(KEY), "JsonObject does not have a field named 'key'");
Preconditions.checkArgument(data.has(DAMAGE_SCALING), "JsonObject does not have a field named 'damageScaling'");
Preconditions.checkArgument(data.has(SOUND), "JsonObject does not have a field named 'sound'");
Preconditions.checkArgument(data.has(DEATH_MESSAGE_TYPE), "JsonObject does not have a field named 'deathMessageType'");
Preconditions.checkArgument(data.has(EXHAUSTION), "JsonObject does not have a field named 'exhaustion'");

// Retrieve values from JSON
String keyValue = data.get(KEY).getAsString();
String damageScalingValue = data.get(DAMAGE_SCALING).getAsString();
String soundValue = data.get(SOUND).getAsString();
String deathMessageTypeValue = data.get(DEATH_MESSAGE_TYPE).getAsString();
float exhaustion = data.get(EXHAUSTION).getAsFloat();

// Parse values
NamespacedKey key = NamespacedKey.fromString(keyValue);
DamageScaling damageScaling = DamageScaling.valueOf(damageScalingValue);
Sound sound = Registry.SOUNDS.get(NamespacedKey.fromString(soundValue));
DamageEffectMock damageEffect = new DamageEffectMock(sound);
DeathMessageType deathMessageType = DeathMessageType.valueOf(deathMessageTypeValue);

// Create object
return new DamageTypeMock(damageScaling, damageEffect, key, deathMessageType, exhaustion);
}

private final DamageScaling damageScaling;
private final DamageEffectMock damageEffect;
private final NamespacedKey key;
private final DeathMessageType deathMessageType;
private final float exhaustion;

public DamageTypeMock(@NotNull DamageScaling damageScaling, @NotNull DamageEffectMock damageEffect, @NotNull NamespacedKey key, @NotNull DeathMessageType deathMessageType, float exhaustion)
{
Preconditions.checkArgument(damageScaling != null, "DamageScaling cannot be null");
Preconditions.checkArgument(damageEffect != null, "DamageEffectMock cannot be null");
Preconditions.checkArgument(key != null, "NamespacedKey cannot be null");
Preconditions.checkArgument(deathMessageType != null, "DeathMessageType cannot be null");

this.damageScaling = damageScaling;
this.damageEffect = damageEffect;
this.key = key;
this.deathMessageType = deathMessageType;
this.exhaustion = exhaustion;
}

/**
* @deprecated Will be replaced with {{@link #from(JsonObject)}}.
*/
@Deprecated(forRemoval = true)
public DamageTypeMock(JsonObject data)
{
this.damageScaling = DamageScaling.valueOf(data.get("damageScaling").getAsString());
Expand Down
@@ -0,0 +1,205 @@
package be.seeseemelk.mockbukkit.damage;

import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.WorldMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import be.seeseemelk.mockbukkit.entity.SkeletonMock;
import be.seeseemelk.mockbukkit.entity.ZombieMock;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.bukkit.damage.DamageScaling;
import org.bukkit.damage.DamageType;
import org.bukkit.damage.DeathMessageType;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;

class DamageSourceMockTest
{

private final Location damageLocation = new Location(new WorldMock(), 0,0,0);

private ServerMock serverMock;
private DamageType damageType;
private Entity causingEntity;
private Entity directEntity;
private DamageSourceMock damageSourceMock;

@BeforeEach
void setUp()
{
serverMock = MockBukkit.mock();

damageType = DamageType.GENERIC;
causingEntity = new SkeletonMock(serverMock, UUID.randomUUID());
directEntity = new ZombieMock(serverMock, UUID.randomUUID());

damageSourceMock = new DamageSourceMock(damageType, causingEntity, directEntity, damageLocation);
}

@AfterEach
void tearDown()
{
MockBukkit.unmock();
}

@Test
void getDamageType() {
assertSame(damageType, damageSourceMock.getDamageType());
}

@Test
void getCausingEntity() {
assertSame(causingEntity, damageSourceMock.getCausingEntity());
}

@Test
void getDirectEntity() {
assertSame(directEntity, damageSourceMock.getDirectEntity());
}

@Test
void getDamageLocation_WhenDamageLocationIsValid() {

Location actual = damageSourceMock.getDamageLocation();

assertNotSame(damageLocation, actual);
assertEquals(damageLocation, actual);
}

@Test
void getDamageLocation_WhenDamageLocationIsNull() {

DamageSourceMock noLocationMock = new DamageSourceMock(damageType, causingEntity, directEntity, null);

Location actual = noLocationMock.getDamageLocation();

assertNull(actual);
}

@Test
void getSourceLocation_WhenDamageLocationIsNotNull() {
Location actual = damageSourceMock.getSourceLocation();

assertNotNull(actual);
assertNotSame(damageLocation, actual);
assertEquals(damageLocation, actual);
}

@Test
void getSourceLocation_WhenDamageLocationIsNullAndDirectEntityLocationIsNotNull() {
DamageSourceMock damageSource = new DamageSourceMock(damageType, causingEntity, directEntity, null);

Location actual = damageSource.getSourceLocation();

assertNotNull(actual);
assertNotSame(causingEntity.getLocation(), actual);
assertEquals(causingEntity.getLocation(), actual);
}

@Test
void getSourceLocation_WhenDamageLocationIsNullAndDirectEntityIsNull() {
DamageSourceMock damageSource = new DamageSourceMock(damageType, causingEntity, null, null);

Location actual = damageSource.getSourceLocation();

assertNull(actual);
}

@Test
void isIndirect_WhenCausingEntityIsEqualToDirectEntity() {

DamageSourceMock sameEntity = new DamageSourceMock(damageType, causingEntity, causingEntity, damageLocation);

boolean actual = sameEntity.isIndirect();

assertFalse(actual);
}

@Test
void isIndirect_WhenCausingEntityIsDifferentFromDirectEntity() {
boolean actual = damageSourceMock.isIndirect();

assertTrue(actual);
}

@Test
void getFoodExhaustion() {
float actual = damageSourceMock.getFoodExhaustion();

assertEquals(damageType.getExhaustion(), actual);
}

@Test
void scalesWithDifficulty_WhenDamageScalingIsNever() {

DamageEffectMock damageEffect = new DamageEffectMock(Sound.ENTITY_ZOMBIE_HURT);
DamageTypeMock neverDamage = new DamageTypeMock(DamageScaling.NEVER, damageEffect, NamespacedKey.fromString(NamespacedKey.MINECRAFT), DeathMessageType.DEFAULT, 0.1F);
DamageSourceMock damageSource = new DamageSourceMock(neverDamage, causingEntity, causingEntity, damageLocation);

boolean actual = damageSource.scalesWithDifficulty();
assertFalse(actual);
}

@Test
void scalesWithDifficulty_WhenDamageScalingIsDoneByPlayer() {

Player player = new PlayerMock(serverMock, "MockBukkit");
DamageSourceMock damageSource = new DamageSourceMock(DamageType.GENERIC, player, directEntity, damageLocation);

boolean actual = damageSource.scalesWithDifficulty();
assertFalse(actual);
}

@Test
void scalesWithDifficulty_WhenDamageScalingIsDoneByLivingEntity() {
DamageSourceMock damageSource = new DamageSourceMock(DamageType.MOB_ATTACK, causingEntity, causingEntity, damageLocation);

boolean actual = damageSource.scalesWithDifficulty();
assertTrue(actual);
}

@Test
void scalesWithDifficulty_WhenDamageScalingIsAlways() {
DamageSourceMock damageSource = new DamageSourceMock(DamageType.PLAYER_EXPLOSION, causingEntity, causingEntity, damageLocation);

boolean actual = damageSource.scalesWithDifficulty();
assertTrue(actual);
}

@Test
void equals_and_hashCode_WhenSameInstance() {
assertEquals(damageSourceMock, damageSourceMock);
assertEquals(damageSourceMock.hashCode(), damageSourceMock.hashCode());
}

@Test
void equals_and_hashCode_WhenIdentical() {
DamageSourceMock copy = new DamageSourceMock(damageType, causingEntity, directEntity, damageLocation);
assertEquals(damageSourceMock, copy);
assertEquals(damageSourceMock.hashCode(), copy.hashCode());
assertEquals(copy, damageSourceMock);
assertEquals(copy.hashCode(), damageSourceMock.hashCode());
}

@Test
void equals_and_hashCode_WhenNotHavingSameType() {
assertNotEquals(damageSourceMock, new Object());
}

}

0 comments on commit adc2d6d

Please sign in to comment.