inventory_mock tests #17

Merged
erns6604 merged 16 commits from inventory_mocks into main 2025-10-30 07:52:55 +01:00
23 changed files with 249 additions and 88 deletions

View File

@ -1,11 +1,11 @@
package Action;
import Job.HasJob;
import Job.JobHolder;
import Job.Wizard;
public class CastAction implements Action {
private Wizard requireWizard(Actor actor) {
if (actor instanceof HasJob hasJob && hasJob.getJob() instanceof Wizard wizard) {
if (actor instanceof JobHolder hasJob && hasJob.getJob() instanceof Wizard wizard) {
return wizard;
}
throw new IllegalStateException(actor + " cannot perform this action without being a Wizard!");

View File

@ -1,6 +1,6 @@
package Action;
import Job.HasJob;
import Job.JobHolder;
import Job.Miner;
import Terrain.Biome;
@ -16,8 +16,7 @@ public class DigAction implements Action {
}
private Miner requireMiner(Actor actor) {
if (actor instanceof HasJob hasJob
&& hasJob.getJob() instanceof Miner miner) {
if (actor.getJob() instanceof Miner miner) {
return miner;
}
throw new IllegalStateException(actor + " cannot perform this action without being a Miner!");

View File

@ -1,6 +1,6 @@
package Action;
import Job.HasJob;
import Job.JobHolder;
import Job.Wizard;
public class LearnSpellAction implements Action {
@ -11,7 +11,7 @@ public class LearnSpellAction implements Action {
}
private Wizard requireWizard(Actor actor) {
if (actor instanceof HasJob hasJob && hasJob.getJob() instanceof Wizard wizard) {
if (actor instanceof JobHolder hasJob && hasJob.getJob() instanceof Wizard wizard) {
return wizard;
}
throw new IllegalStateException(actor + " cannot perform this action without being a Wizard!");

View File

@ -1,7 +0,0 @@
package Character;
import java.util.List;
public interface HasInventory {
List<String> getInventory();
}

View File

@ -4,7 +4,7 @@ package Entity;
import java.util.ArrayList;
import java.util.List;
public abstract class Entity implements HasPosition {
public abstract class Entity implements Positionable {
protected String name;
protected Position position;
private static final List<Entity> entities = new ArrayList<Entity>();

View File

@ -9,15 +9,15 @@ import Combat.Spell;
import Inventory.Inventory;
import Item.Equipment;
import Job.Job;
import Job.HasJob;
import Inventory.HasInventory;
import Job.JobHolder;
import Inventory.InventoryHolder;
import Inventory.HasSpellBook;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Player extends Entity implements Movable, Actor, HasInventory, HasSpellBook, HasJob, HasHealth, HasMana, HasConditions {
public class Player extends Entity implements Movable, Actor, InventoryHolder, HasSpellBook, JobHolder, HasHealth, HasMana, HasConditions {
protected int health;
protected int mana;
protected int strength;
@ -43,6 +43,20 @@ public class Player extends Entity implements Movable, Actor, HasInventory, HasS
super(name);
}
public Player(String name, Inventory inventory) {
super(name);
this.inventory = inventory;
this.position = new Position(0,0);
}
public Player(String name, Job job, Inventory inventory) {
super(name);
this.job = job;
this.inventory = inventory;
this.position = new Position(0,0);
}
@Override
public void moveTo(Position position) {
if(canMoveTo(position)){
@ -52,7 +66,9 @@ public class Player extends Entity implements Movable, Actor, HasInventory, HasS
@Override
public boolean canMoveTo(Position position) {
return true;
boolean withinX = (position.x() - 2) < this.position.x() && this.position.x() < (position.x() + 2);
boolean withinY = (position.y() - 2) < this.position.y() && this.position.y() < (position.y() + 2);
return withinX && withinY;
}
public Job getJob() {
return job;

View File

@ -1,6 +1,6 @@
package Entity;
public interface HasPosition {
public interface Positionable {
Position getPosition();
void setPosition(Position position);
}

View File

@ -1,7 +0,0 @@
package Inventory;
import java.util.List;
public interface HasInventory {
Inventory getInventory();
}

View File

@ -1,6 +1,5 @@
package Inventory;
import Item.Item;
import Item.ItemStack;
import java.util.ArrayList;
@ -27,11 +26,10 @@ public class Inventory {
public void addItem(ItemStack stack) {
if (stack.getWeight() + getCurrentWeight() > maxWeight) {
if(stack.isSingleItem()) return;
trySubstack(stack);
return;
} else {
items.add(stack);
}
items.add(stack);
}
private void trySubstack(ItemStack stack) {
@ -49,26 +47,9 @@ public class Inventory {
public int getCurrentWeight() {
int currentWeight = 0;
for (ItemStack item : items) {
currentWeight += item.getItem().getWeight();
for (ItemStack stack : items) {
currentWeight += stack.getWeight();
}
return currentWeight;
}
private int calculateStackWeight(ItemStack stack) {
return stack.getItem().getWeight() * stack.getQuantity();
}
public boolean containsItem(Item item) {
for (ItemStack stack : items) {
if (stack.item().equals(item)) {
return true;
}
}
return false;
}
public int getMaxWeight() {
return maxWeight;
}
}

View File

@ -0,0 +1,5 @@
package Inventory;
public interface InventoryHolder {
Inventory getInventory();
}

View File

@ -1,7 +1,5 @@
package Item;
import Inventory.Inventory;
public record ItemStack(Item item, int quantity) {
public ItemStack {
if (quantity <= 0) {
@ -16,10 +14,6 @@ public record ItemStack(Item item, int quantity) {
return quantity;
}
public boolean isSingleItem() {
return quantity == 1;
}
public int getWeight() {
return item.getWeight() * quantity;
}

View File

@ -3,8 +3,6 @@ package Job;
import Shared.ExperienceTable;
import Shared.Levelable;
import java.util.Objects;
public abstract class Job implements Levelable {
protected int level;
protected int experience;
@ -43,21 +41,4 @@ public abstract class Job implements Levelable {
level++;
}
@Override
public String toString() {
return String.format("Job: %s. Level: %d", name, level);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
return o != null && getClass() == o.getClass();
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}

View File

@ -1,6 +1,6 @@
package Job;
public interface HasJob {
public interface JobHolder {
Job getJob();
void learnJob(Job job);
}

View File

@ -1,19 +1,19 @@
package Job;
import Inventory.HasInventory;
import Inventory.InventoryHolder;
import Item.ItemStack;
import Terrain.Biome;
public class Miner extends Job {
HasInventory actor;
InventoryHolder actor;
public Miner(HasInventory actor) {
public Miner(InventoryHolder actor) {
super("Miner");
this.actor = actor;
}
public HasInventory getActor() {
public InventoryHolder getActor() {
return actor;
}

View File

@ -41,6 +41,9 @@ public class LootTable<T> {
return entry.item();
}
}
// Unreachable code. entries always have an entry or the class cant be instantiated.
// Cant put system into this state.
// only have a return here due to compiler requiring it.
return null;
}

View File

@ -0,0 +1,14 @@
import Terrain.Biome;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class BiomeTest {
@Test
void instantiates_with_name() {
var biome = Biome.COAST;
assertEquals("Coast", biome.getName());
}
}

View File

@ -0,0 +1,38 @@
import Action.DigAction;
import Entity.Player;
import Job.Miner;
import Terrain.Biome;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
public class DigActionTest {
@Test
void can_be_executed_as_miner() {
var mockMiner = mock(Miner.class);
var player = mock(Player.class);
when(player.getJob()).thenReturn(mockMiner);
var biome = mock(Biome.class);
var action = new DigAction(biome);
action.execute(player);
verify(mockMiner, times(1)).dig(biome);
}
@Test
void digging_when_not_miner_throws_error() {
var player = mock(Player.class);
when(player.getJob()).thenReturn(null);
var biome = mock(Biome.class);
var action = new DigAction(biome);
assertThrows(IllegalStateException.class, () -> action.execute(player));
}
@Test
void digging_when_not_have_job_throws_error() {
var player = mock(Player.class);
var biome = mock(Biome.class);
var action = new DigAction(biome);
assertThrows(IllegalStateException.class, () -> action.execute(player));
}
}

View File

@ -40,11 +40,12 @@ public class InventoryTest {
var item = new BasicItem("iron_sword", "Iron Sword", 10);
var stack = new ItemStack(item, 1);
inventory.addItem(stack);
assertThat(inventory.getItems().size(), is(0));
}
@Test
void stack_can_be_added_up_to_capacity() {
void add_substack_if_item_fits() {
var inventory = new Inventory(5);
var item = new BasicItem("sand_grain", "Sand Grain", 1);
var stack = new ItemStack(item, 8);
@ -57,7 +58,21 @@ public class InventoryTest {
hasProperty("quantity", equalTo(5)))
));
}
@Test
void current_weight_is_zero_if_no_item_is_added() {
var inventory = new Inventory(5);
assertThat(inventory.getCurrentWeight(), is(0));
}
@Test
void current_weight_calculates_correctly() {
var inventory = new Inventory(10);
var item = new BasicItem("iron_sword", "Iron Sword", 5);
var item2 = new BasicItem("berry", "Berry", 1);
inventory.addItem(new ItemStack(item, 1));
inventory.addItem(new ItemStack(item2, 2));
assertThat(inventory.getCurrentWeight(), is(7));
}
}

View File

@ -0,0 +1,29 @@
import Item.BasicItem;
import Item.ItemStack;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ItemStackTest {
@Test
void instantiated_with_no_quantity_throws_exception() {
assertThrows(IllegalArgumentException.class, () -> new ItemStack(
new BasicItem("id", "name", 5), 0
));
}
@Test
void instantiated_with_negative_quantity_throws_exception() {
assertThrows(IllegalArgumentException.class, () -> new ItemStack(
new BasicItem("id", "name", 5), -4
));
}
@Test
void can_be_created_with_positive_quantity() {
var i = new ItemStack(new BasicItem("id", "name", 5), 5);
assertThat(i, instanceOf(ItemStack.class));
}
}

View File

@ -0,0 +1,27 @@
import Item.BasicItem;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ItemTest {
private BasicItem item() {
return new BasicItem("item_id", "item", 5);
}
@Test
void instantiates_with_id() {
var i = item();
assertEquals("item_id", i.getId());
}
@Test
void instantiate_with_name() {
var item = item();
assertEquals("item", item.getName());
}
@Test
void instantiates_with_weight() {
var i = item();
assertEquals(5, i.getWeight());
}
}

View File

@ -42,5 +42,4 @@ public class LootTableTest {
assertThat(result, equalTo("Iron"));
}
}

View File

@ -1,4 +1,6 @@
import Action.DigAction;
import Entity.Player;
import Inventory.Inventory;
import Job.Miner;
import Shared.RandomProvider;
import Terrain.Biome;
@ -7,9 +9,9 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
public class MinerTest {
private Player defaultPlayer() {return new Player("John"); }
@ -21,6 +23,12 @@ public class MinerTest {
assertEquals(2, job.getLevel());
}
@Test
void can_be_created_with_player() {
var miner = new Miner(defaultPlayer());
assertThat(miner.getActor(), equalTo(defaultPlayer()));
}
@Test
void can_gain_xp() {
var job = new Miner(defaultPlayer());
@ -30,7 +38,7 @@ public class MinerTest {
@Test
void level_up_when_experience_cap_is_reached() {
var job = new Miner(defaultPlayer());
Miner job = new Miner(defaultPlayer());
job.gainExperience(job.remainingXpUntilLevelUp());
assertEquals(2, job.getLevel());
}
@ -65,6 +73,15 @@ public class MinerTest {
)
);
}
@Test
void dig_use_workers_inventory() {
var mockInventory = mock(Inventory.class);
var miner = new Miner(new Player("John", mockInventory));
miner.dig(Biome.MOUNTAIN);
verify(mockInventory).addItem(any());
}
}

View File

@ -2,14 +2,13 @@ import Action.DigAction;
import Action.LearnSpellAction;
import Combat.OffensiveDamageSpell;
import Entity.Position;
import Inventory.Inventory;
import Job.Miner;
import Entity.Player;
import Terrain.Biome;
import org.junit.jupiter.api.Test;
import Job.Wizard;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ -19,6 +18,15 @@ class PlayerTest {
return new Player("abc");
}
@Test
void player_can_be_created_with_job_and_inventory() {
var job = mock(Miner.class);
var inventory = mock(Inventory.class);
var player = new Player("abc", job, inventory);
assertThat(player, instanceOf(Player.class));
}
@Test
public void is_dead_if_health_is_zero() {
var p = defaultPlayer();
@ -26,6 +34,13 @@ class PlayerTest {
assertFalse(p.isAlive());
}
@Test
public void is_alive_if_has_health() {
var p = defaultPlayer();
p.setHealth(10);
assertTrue(p.isAlive());
}
@Test
void get_health_returns_health() {
var p = defaultPlayer();
@ -62,6 +77,37 @@ class PlayerTest {
assertEquals(new Position(1,1), p.getPosition());
}
@Test
public void can_not_walk_two_spaces_y() {
var p = defaultPlayer();
p.moveTo(new Position(1,2));
assertEquals(new Position(0,0), p.getPosition());
}
@Test
public void can_not_walk_two_spaces_x() {
var p = defaultPlayer();
p.moveTo(new Position(2,1));
assertEquals(new Position(0,0), p.getPosition());
}
@Test
void can_not_walk_two_spaces_y_negative() {
var p = defaultPlayer();
p.setPosition(new Position(3,3));
p.moveTo(new Position(1,3));
assertEquals(new Position(3,3), p.getPosition());
}
@Test
void can_not_walk_two_spaces_x_negative() {
var p = defaultPlayer();
p.setPosition(new Position(3,3));
p.moveTo(new Position(3,1));
assertEquals(new Position(3,3), p.getPosition());
}
@Test
public void can_change_job() {
var p = defaultPlayer();
@ -81,6 +127,17 @@ class PlayerTest {
verify(mockAction, times(1)).execute(p);
}
@Test
void miner_can_dig_multiple_times() {
var p = new Player("John");
p.learnJob(new Miner(p));
var mockAction = mock(DigAction.class);
for(int i = 0; i < 10; i++) {
p.performAction(mockAction);
}
verify(mockAction, times(10)).execute(p);
}
@Test
void wizard_can_learn_spell() {
var p = new Player("Bob");