Преглед на файлове

added tests from original text adventure

Ondřej Schlaichert преди 8 месеца
родител
ревизия
1c3d0698c1

+ 81 - 0
src/test/java/eu/oschl/textadventure/BaseGameTest.java

@@ -0,0 +1,81 @@
+package eu.oschl.textadventure;
+
+import eu.oschl.textadventure.entities.Enemy;
+import eu.oschl.textadventure.map.Blockage;
+import eu.oschl.textadventure.map.Passage;
+import eu.oschl.textadventure.map.Room;
+import eu.oschl.textadventure.objects.Button;
+import eu.oschl.textadventure.objects.Weapon;
+import org.junit.jupiter.api.BeforeEach;
+
+/**
+ * Provides a base game object for other tests to use.
+ *
+ * @author Ondřej Schlaichert
+ */
+public abstract class BaseGameTest {
+    protected Game game;
+
+    @BeforeEach
+    void setUpGame() {
+        var prologue = "This is a prologue.";
+        var epilogue = "This is an epilogue.";
+
+        var unknownCommandMessages = new String[]{
+                "This is a message informing the player that the command is unknown.",
+        };
+
+        var room1 = new Room(
+                "Room 1",
+                "This is room number one."
+        );
+
+        var room2 = new Room(
+                "Room 2",
+                "This is room number two."
+        );
+
+        var passage = new Passage("Passage", true);
+        passage.addRoom(room1);
+        passage.addRoom(room2);
+
+        var blockage = new Blockage("Blockage", 1);
+        passage.setBlockage(blockage);
+
+        var button = new Button(
+                "Button",
+                "This is a button.",
+                "You have pressed the button.",
+                blockage
+        );
+        room1.addObject(button);
+
+        var weapon = new Weapon(
+                "Sword",
+                "This is a sword.",
+                "You have picked up the sword.",
+                10
+        );
+        room1.addObject(weapon);
+
+        var finalBoss = new Enemy(
+                "Enemy",
+                "This is an enemy.",
+                "You have defeated the enemy!",
+                10,
+                true
+        );
+        room2.setEnemy(finalBoss);
+
+        game = new Game(
+                prologue,
+                epilogue,
+                unknownCommandMessages
+        );
+
+        game.addRoom(room1);
+        game.addRoom(room2);
+
+        game.setCurrentRoom(room1);
+    }
+}

+ 120 - 0
src/test/java/eu/oschl/textadventure/GameTest.java

@@ -0,0 +1,120 @@
+package eu.oschl.textadventure;
+
+import eu.oschl.textadventure.exceptions.InvalidGameState;
+import eu.oschl.textadventure.map.Passage;
+import eu.oschl.textadventure.map.Room;
+import eu.oschl.textadventure.objects.Button;
+import eu.oschl.textadventure.objects.Weapon;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Game class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class GameTest extends BaseGameTest {
+    @Test
+    void testGameFieldsAreInitializedCorrectly() {
+        assertEquals("This is a prologue.", game.getPrologue());
+        assertEquals("This is an epilogue.", game.getEpilogue());
+        assertArrayEquals(
+                new String[]{"This is a message informing the player that the command is unknown."},
+                game.getUnknownCommandMessages()
+        );
+        assertNotNull(game.getInventory());
+        assertEquals(2, game.getRooms().size());
+        assertTrue(game.isRunning());
+    }
+
+    @Test
+    void testSetCurrentRoomChangesRoomAndPreservesReference() {
+        Room room2 = game.getRooms().get(1);
+        game.setCurrentRoom(room2);
+
+        assertEquals(room2, game.getCurrentRoom());
+    }
+
+    @Test
+    void testAddPreviousPassageAndGetLastPassage() {
+        Passage passage = game.getRooms().getFirst().getPassages().iterator().next();
+        game.addPreviousPassage(passage);
+
+        Optional<Passage> result = game.getLastPassage();
+        assertTrue(result.isPresent());
+        assertEquals(passage, result.get());
+    }
+
+    @Test
+    void testGetLastPassageWhenEmptyReturnsEmpty() {
+        assertTrue(game.getPreviousPassages().isEmpty());
+        assertTrue(game.getLastPassage().isEmpty());
+    }
+
+    @Test
+    void testRemoveLastPassageSucceedsWhenNotEmpty() {
+        Passage passage = game.getRooms().get(0).getPassages().iterator().next();
+        game.addPreviousPassage(passage);
+        assertDoesNotThrow(() -> game.removeLastPassage());
+        assertTrue(game.getPreviousPassages().isEmpty());
+    }
+
+    @Test
+    void testRemoveLastPassageThrowsWhenEmpty() {
+        assertThrows(InvalidGameState.class, () -> game.removeLastPassage());
+    }
+
+    @Test
+    void testFinishStopsGame() {
+        game.finish();
+        assertFalse(game.isRunning());
+    }
+
+    @Test
+    void testGameTraversal() {
+        assertTrue(game.isRunning());
+
+        var room1 = game.getCurrentRoom();
+        var passage = room1.getPassages().iterator().next();
+        assertEquals(1, room1.getPassages().size());
+
+        var room2 = passage.getOtherRoom(room1);
+
+        assertFalse(passage.passThrough(false));
+        assertEquals(room1, game.getCurrentRoom());
+
+        Weapon weapon = null;
+        Button button = null;
+        for (var object : room1.getObjects()) {
+            if (object instanceof Weapon w) {
+                weapon = w;
+            }
+
+            if (object instanceof Button b) {
+                button = b;
+            }
+        }
+
+        assertNotNull(weapon);
+        weapon.pickUp();
+
+        assertNotNull(button);
+        button.press();
+
+        assertTrue(passage.passThrough(false));
+        assertEquals(room2, game.getCurrentRoom());
+
+        assertTrue(game.getCurrentRoom().getEnemy().isPresent());
+        assertTrue(game.getCurrentRoom().getEnemy().get().isAlive());
+        assertTrue(game.getCurrentRoom().isBlockedByEnemy());
+
+        assertTrue(game.getCurrentRoom().getEnemy().get().kill());
+
+        assertFalse(game.getCurrentRoom().isBlockedByEnemy());
+        assertFalse(game.getCurrentRoom().getEnemy().get().isAlive());
+        assertFalse(game.isRunning());
+    }
+}

+ 86 - 0
src/test/java/eu/oschl/textadventure/InventoryTest.java

@@ -0,0 +1,86 @@
+package eu.oschl.textadventure;
+
+import eu.oschl.textadventure.map.Blockage;
+import eu.oschl.textadventure.map.Room;
+import eu.oschl.textadventure.objects.InventoryItem;
+import eu.oschl.textadventure.objects.Weapon;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Inventory class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class InventoryTest {
+    private Inventory inventory;
+
+    @BeforeEach
+    void setUp() {
+        inventory = new Inventory();
+    }
+
+    @Test
+    void testConstructorInitializesEmptyInventory() {
+        assertTrue(inventory.getItems().isEmpty());
+        assertTrue(inventory.getWeapon().isEmpty());
+    }
+
+    @Test
+    void testAddItemSucceedsWhenUnderLimit() {
+        for (int i = 0; i < 5; i++) {
+            InventoryItem item = makeItem("Item" + i);
+            assertTrue(inventory.addItem(item));
+        }
+    }
+
+    @Test
+    void testAddItemFailsWhenOverLimit() {
+        for (int i = 0; i < 5; i++) {
+            assertTrue(inventory.addItem(makeItem("Item" + i)));
+        }
+
+        InventoryItem extra = makeItem("Overflow");
+        assertFalse(inventory.addItem(extra));
+    }
+
+    @Test
+    void testRemoveItemSucceedsIfPresent() {
+        InventoryItem item = makeItem("Potion");
+        inventory.addItem(item);
+
+        assertTrue(inventory.removeItem(item));
+        assertFalse(inventory.getItems().contains(item));
+    }
+
+    @Test
+    void testRemoveItemFailsIfAbsent() {
+        InventoryItem item = makeItem("Ghost Item");
+
+        assertFalse(inventory.removeItem(item));
+    }
+
+    @Test
+    void testSetWeaponReplacesWeapon() {
+        Weapon axe = new Weapon("Axe", "Choppy", "CHOP", 15);
+        Weapon sword = new Weapon("Sword", "Sharp", "SLASH", 25);
+
+        inventory.setWeapon(axe);
+        assertEquals(axe, inventory.getWeapon().orElse(null));
+
+        inventory.setWeapon(sword);
+        assertEquals(sword, inventory.getWeapon().orElse(null));
+    }
+
+    private InventoryItem makeItem(String name) {
+        return new InventoryItem(
+                name,
+                "Desc of " + name,
+                "Use text for " + name,
+                new Room[0],
+                new Blockage("Fake", 1)
+        );
+    }
+}

+ 93 - 0
src/test/java/eu/oschl/textadventure/entities/EnemyTest.java

@@ -0,0 +1,93 @@
+package eu.oschl.textadventure.entities;
+
+import eu.oschl.textadventure.BaseGameTest;
+import eu.oschl.textadventure.objects.Weapon;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Enemy class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class EnemyTest extends BaseGameTest {
+    @Test
+    void testConstructorInitializesFields() {
+        Enemy enemy = new Enemy("Goblin", "A mean goblin", "You have slain the goblin!", 5, true);
+
+        assertEquals("Goblin", enemy.getName());
+        assertEquals("A mean goblin", enemy.getDescription());
+        assertEquals(Optional.of("You have slain the goblin!"), enemy.getKillText());
+        assertEquals(5, enemy.getStrength());
+        assertTrue(enemy.isFinalBoss());
+        assertTrue(enemy.isAlive());
+    }
+
+    @Test
+    void testKillWithoutWeaponAndStrengthZeroSucceeds() {
+        Enemy enemy = new Enemy("Wimp", "A weakling", 0);
+        enemy.setGame(game);
+
+        boolean result = enemy.kill();
+
+        assertTrue(result);
+        assertFalse(enemy.isAlive());
+    }
+
+    @Test
+    void testKillWithoutWeaponAndStrengthPositiveFails() {
+        Enemy enemy = new Enemy("Troll", "Big and scary", 10);
+        enemy.setGame(game);
+
+        boolean result = enemy.kill();
+
+        assertFalse(result);
+        assertTrue(enemy.isAlive());
+    }
+
+    @Test
+    void testKillWithWeakWeaponFails() {
+        Weapon knife = new Weapon("Knife", "A small knife", "You attacked with the knife", 1);
+        game.getInventory().setWeapon(knife);
+
+        Enemy enemy = new Enemy("Orc", "Strong", 5);
+        enemy.setGame(game);
+
+        boolean result = enemy.kill();
+
+        assertFalse(result);
+        assertTrue(enemy.isAlive());
+    }
+
+    @Test
+    void testKillWithStrongWeaponSucceeds() {
+        Weapon sword = new Weapon("Sword", "Sharp and deadly", "You attacked with the sword", 10);
+        game.getInventory().setWeapon(sword);
+
+        Enemy enemy = new Enemy("Bandit", "Sneaky thief", 5);
+        enemy.setGame(game);
+
+        boolean result = enemy.kill();
+
+        assertTrue(result);
+        assertFalse(enemy.isAlive());
+    }
+
+    @Test
+    void testKillFinalBossWithSufficientWeaponFinishesGame() {
+        Weapon godSword = new Weapon("Excalibur", "Crazy!!!", "You attacked with the Excalibur", 100);
+        game.getInventory().setWeapon(godSword);
+
+        Enemy finalBoss = new Enemy("Dragon", "The final challenge", "You have vanquished the dragon!", 50, true);
+        finalBoss.setGame(game);
+
+        boolean result = finalBoss.kill();
+
+        assertTrue(result);
+        assertFalse(finalBoss.isAlive());
+        assertFalse(game.isRunning());
+    }
+}

+ 47 - 0
src/test/java/eu/oschl/textadventure/map/BlockageTest.java

@@ -0,0 +1,47 @@
+package eu.oschl.textadventure.map;
+
+import eu.oschl.textadventure.BaseGameTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Blockage class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class BlockageTest extends BaseGameTest {
+    @Test
+    void testConstructorInitializesFields() {
+        Blockage blockage = new Blockage("A locked door", 3);
+
+        assertEquals("A locked door", blockage.getDescription());
+        assertEquals(3, blockage.getRequiredInteractionsToPass());
+    }
+
+    @Test
+    void testInteractReducesInteractionCount() {
+        Blockage blockage = new Blockage("Puzzle", 2);
+        assertFalse(blockage.canPass());
+
+        blockage.interact();
+        assertEquals(1, blockage.getRequiredInteractionsToPass());
+        assertFalse(blockage.canPass());
+
+        blockage.interact();
+        assertEquals(0, blockage.getRequiredInteractionsToPass());
+        assertTrue(blockage.canPass());
+    }
+
+    @Test
+    void testCanPassReturnsTrueWhenCountIsZeroOrLess() {
+        Blockage blockage = new Blockage("Final door", 1);
+        assertFalse(blockage.canPass());
+
+        blockage.interact();
+        assertTrue(blockage.canPass());
+
+        blockage.interact();
+        assertTrue(blockage.canPass());
+    }
+}

+ 166 - 0
src/test/java/eu/oschl/textadventure/map/PassageTest.java

@@ -0,0 +1,166 @@
+package eu.oschl.textadventure.map;
+
+import eu.oschl.textadventure.BaseGameTest;
+import eu.oschl.textadventure.exceptions.InvalidGameState;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Passage class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class PassageTest extends BaseGameTest {
+    @Test
+    void testConstructorSetsFieldsCorrectly() {
+        Passage passage = new Passage("Tunnel", "A dark tunnel", true);
+
+        assertEquals("Tunnel", passage.getName());
+        assertEquals(Optional.of("A dark tunnel"), passage.getDescription());
+        assertTrue(passage.isSeeThrough());
+        assertNotNull(passage.getRooms());
+        assertEquals(2, passage.getRooms().length);
+    }
+
+    @Test
+    void testSetGameAlsoSetsGameOnBlockage() {
+        Passage passage = new Passage("Hidden Path", true);
+        Blockage blockage = new Blockage("Stone wall", 2);
+        passage.setBlockage(blockage);
+
+        passage.setGame(game);
+    }
+
+    @Test
+    void testAddRoomAssociatesRoomsCorrectly() {
+        Passage passage = new Passage("Bridge", true);
+        passage.setGame(game);
+
+        Room room1 = game.getRooms().get(0);
+        Room room2 = game.getRooms().get(1);
+
+        passage.addRoom(room1);
+        passage.addRoom(room2);
+
+        Room[] connected = passage.getRooms();
+        assertTrue(connected[0] == room1 || connected[1] == room1);
+        assertTrue(connected[0] == room2 || connected[1] == room2);
+    }
+
+    @Test
+    void testAddThirdRoomThrows() {
+        Passage passage = new Passage("Impossible Triangle", true);
+        passage.setGame(game);
+
+        Room extra = new Room("Extra", "Extra room");
+        passage.addRoom(game.getRooms().get(0));
+        passage.addRoom(game.getRooms().get(1));
+
+        assertThrows(InvalidGameState.class, () -> passage.addRoom(extra));
+    }
+
+    @Test
+    void testCanPassWithUninteractedBlockageFails() {
+        Passage passage = game.getRooms().getFirst().getPassages().iterator().next();
+        game.setCurrentRoom(game.getRooms().getFirst());
+
+        assertFalse(passage.canPass());
+    }
+
+    @Test
+    void testCanPassWithClearedBlockageSucceeds() {
+        Passage passage = game.getRooms().get(0).getPassages().iterator().next();
+        Blockage blockage = passage.getBlockage().orElseThrow();
+
+        blockage.interact();
+        assertTrue(blockage.canPass());
+
+        assertTrue(passage.canPass());
+    }
+
+    @Test
+    void testCanPassFailsIfNotConnectedToCurrentRoom() {
+        Passage passage = new Passage("Disconnected", true);
+        passage.setGame(game);
+
+        Room outsider = new Room("Outsider", "Nowhere");
+        passage.addRoom(outsider);
+        passage.addRoom(game.getRooms().get(1));
+
+        game.setCurrentRoom(game.getRooms().get(0));
+
+        assertFalse(passage.canPass());
+    }
+
+    @Test
+    void testCanPassFailsWhenEnemyIsPresent() {
+        game.setCurrentRoom(game.getRooms().get(1));
+        Passage passage = game.getRooms().get(1).getPassages().iterator().next();
+
+        assertFalse(passage.canPass());
+    }
+
+    @Test
+    void testCanPassWhenGoingBackFromEnemyRoom() {
+        Passage passage = game.getRooms().get(0).getPassages().iterator().next();
+        Blockage blockage = passage.getBlockage().orElseThrow();
+        blockage.interact();
+
+        game.addPreviousPassage(passage);
+        game.setCurrentRoom(game.getRooms().get(1));
+
+        assertTrue(passage.canPass());
+    }
+
+    @Test
+    void testPassThroughSuccessMovesPlayer() {
+        Passage passage = game.getRooms().getFirst().getPassages().iterator().next();
+        Blockage blockage = passage.getBlockage().orElseThrow();
+        blockage.interact();
+
+        Room to = game.getRooms().get(1);
+
+        boolean result = passage.passThrough(false);
+
+        assertTrue(result);
+        assertEquals(to, game.getCurrentRoom());
+    }
+
+    @Test
+    void testPassThroughFailsIfBlocked() {
+        Passage passage = game.getRooms().getFirst().getPassages().iterator().next();
+        passage.getBlockage().orElseThrow();
+
+        boolean result = passage.passThrough(false);
+
+        assertFalse(result);
+        assertEquals(game.getRooms().getFirst(), game.getCurrentRoom());
+    }
+
+    @Test
+    void testGetOtherRoomReturnsCorrectRoom() {
+        Passage passage = game.getRooms().get(0).getPassages().iterator().next();
+        Room room1 = game.getRooms().get(0);
+        Room room2 = game.getRooms().get(1);
+
+        assertEquals(room2, passage.getOtherRoom(room1));
+        assertEquals(room1, passage.getOtherRoom(room2));
+    }
+
+    @Test
+    void testGetOtherRoomThrowsIfRoomNotInPassage() {
+        Passage passage = new Passage("Secret Path", true);
+        Room roomA = new Room("A", "A");
+        Room roomB = new Room("B", "B");
+
+        passage.addRoom(roomA);
+        passage.addRoom(roomB);
+
+        Room outsider = new Room("Outsider", "Nope");
+
+        assertThrows(InvalidGameState.class, () -> passage.getOtherRoom(outsider));
+    }
+}

+ 84 - 0
src/test/java/eu/oschl/textadventure/map/RoomTest.java

@@ -0,0 +1,84 @@
+package eu.oschl.textadventure.map;
+
+import eu.oschl.textadventure.BaseGameTest;
+import eu.oschl.textadventure.entities.Enemy;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Room class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class RoomTest extends BaseGameTest {
+    @Test
+    void testConstructorInitializesFieldsWithEnterText() {
+        Room room = new Room("Library", "A dusty old room.", "You have entered the library.");
+        assertEquals("Library", room.getName());
+        assertEquals("A dusty old room.", room.getDescription());
+        assertEquals(Optional.of("You have entered the library."), room.getEnterText());
+        assertTrue(room.getPassages().isEmpty());
+        assertTrue(room.getObjects().isEmpty());
+        assertFalse(room.wasEntered());
+    }
+
+    @Test
+    void testConstructorInitializesFieldsWithoutEnterText() {
+        Room room = new Room("Hall", "A large echoing hall.");
+        assertEquals("Hall", room.getName());
+        assertEquals("A large echoing hall.", room.getDescription());
+        assertEquals(Optional.empty(), room.getEnterText());
+    }
+
+    @Test
+    void testEnterMarksRoomAsEnteredAndSetsCurrentRoom() {
+        Room room = game.getRooms().get(1);
+        assertNotEquals(room, game.getCurrentRoom());
+
+        boolean result = room.enter();
+
+        assertTrue(result);
+        assertEquals(room, game.getCurrentRoom());
+        assertTrue(room.wasEntered());
+    }
+
+    @Test
+    void testAddPassageLinksPassageAndGame() {
+        Room room = new Room("Secret", "Hidden behind the bookshelf");
+        room.setGame(game);
+
+        Passage passage = new Passage("Tunnel", true);
+        room.addPassage(passage);
+
+        assertTrue(room.getPassages().contains(passage));
+    }
+
+    @Test
+    void testIsBlockedByEnemyReturnsCorrectly() {
+        Room room = new Room("Arena", "Fight here");
+        room.setGame(game);
+
+        Enemy enemy = new Enemy("Orc", "Strong", 0);
+        room.setEnemy(enemy);
+
+        assertTrue(room.isBlockedByEnemy());
+
+        enemy.kill();
+        assertFalse(room.isBlockedByEnemy());
+    }
+
+    @Test
+    void testSetEnemyNullRemovesEnemy() {
+        Room room = new Room("Void", "Empty");
+        room.setGame(game);
+
+        room.setEnemy(new Enemy("Zombie", "Undead", 1));
+        assertTrue(room.getEnemy().isPresent());
+
+        room.setEnemy(null);
+        assertTrue(room.getEnemy().isEmpty());
+    }
+}

+ 73 - 0
src/test/java/eu/oschl/textadventure/objects/ButtonTest.java

@@ -0,0 +1,73 @@
+package eu.oschl.textadventure.objects;
+
+import eu.oschl.textadventure.BaseGameTest;
+import eu.oschl.textadventure.map.Blockage;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Button class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class ButtonTest extends BaseGameTest {
+    private Blockage blockage;
+    private Button button;
+
+    @BeforeEach
+    void setUp() {
+        blockage = new Blockage("Door", 1);
+        button = new Button(
+                "Red Button",
+                "A suspiciously large red button.",
+                "You hear a satisfying *click*.",
+                blockage
+        );
+    }
+
+    @Test
+    void testConstructorInitializesFields() {
+        assertEquals("Red Button", button.getName());
+        assertEquals("A suspiciously large red button.", button.getDescription());
+        assertEquals("You hear a satisfying *click*.", button.getPressText());
+        assertEquals(blockage, button.getInteractsWith());
+        assertFalse(button.isPressed());
+    }
+
+    @Test
+    void testPressReturnsTrueFirstTime() {
+        assertEquals(1, blockage.getRequiredInteractionsToPass());
+
+        boolean result = button.press();
+
+        assertTrue(result);
+        assertTrue(button.isPressed());
+        assertEquals(0, blockage.getRequiredInteractionsToPass());
+    }
+
+    @Test
+    void testPressReturnsFalseIfAlreadyPressed() {
+        assertTrue(button.press());
+        assertFalse(button.press());
+    }
+
+    @Test
+    void testMultipleButtonsAffectSameBlockage() {
+        Button anotherButton = new Button(
+                "Blue Button",
+                "A secondary button.",
+                "You press it too.",
+                blockage
+        );
+
+        assertTrue(button.press());
+        assertFalse(button.press());
+
+        assertEquals(0, blockage.getRequiredInteractionsToPass());
+
+        assertTrue(anotherButton.press());
+        assertTrue(anotherButton.isPressed());
+    }
+}

+ 126 - 0
src/test/java/eu/oschl/textadventure/objects/InventoryItemTest.java

@@ -0,0 +1,126 @@
+package eu.oschl.textadventure.objects;
+
+import eu.oschl.textadventure.BaseGameTest;
+import eu.oschl.textadventure.map.Blockage;
+import eu.oschl.textadventure.map.Room;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the InventoryItem class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class InventoryItemTest extends BaseGameTest {
+    @Test
+    void testConstructorInitializesFields() {
+        Blockage blockage = new Blockage("Door", 1);
+        Room[] usableRooms = { game.getCurrentRoom() };
+
+        InventoryItem item = new InventoryItem(
+                "Key",
+                "A small bronze key.",
+                "You insert the key into the lock.",
+                usableRooms,
+                blockage
+        );
+
+        assertEquals("Key", item.getName());
+        assertEquals("A small bronze key.", item.getDescription());
+        assertEquals("You insert the key into the lock.", item.getUseText());
+        assertArrayEquals(usableRooms, item.getCanBeUsedIn());
+        assertEquals(blockage, item.getInteractsWith());
+    }
+
+    @Test
+    void testPickUpSucceedsWhenRoomUnblocked() {
+        Room current = game.getCurrentRoom();
+
+        InventoryItem item = new InventoryItem(
+                "Gem",
+                "A glowing gem.",
+                "You press it into the socket.",
+                new Room[]{ current },
+                new Blockage("Gem Lock", 1)
+        );
+
+        current.addObject(item);
+        item.setGame(game);
+
+        boolean result = item.pickUp();
+
+        assertTrue(result);
+        assertTrue(game.getInventory().getItems().contains(item));
+        assertFalse(current.getObjects().contains(item));
+    }
+
+    @Test
+    void testPickUpFailsIfRoomBlockedByEnemy() {
+        Room enemyRoom = game.getRooms().get(1);
+        game.setCurrentRoom(enemyRoom);
+
+        InventoryItem item = new InventoryItem(
+                "Potion",
+                "A health potion.",
+                "You drink it.",
+                new Room[]{ enemyRoom },
+                new Blockage("Blocked", 1)
+        );
+
+        enemyRoom.addObject(item);
+        item.setGame(game);
+
+        boolean result = item.pickUp();
+
+        assertFalse(result);
+        assertFalse(game.getInventory().getItems().contains(item));
+        assertTrue(enemyRoom.getObjects().contains(item));
+    }
+
+    @Test
+    void testUseSucceedsInCorrectRoom() {
+        Room allowed = game.getCurrentRoom();
+        Blockage blockage = new Blockage("Vault", 1);
+
+        InventoryItem item = new InventoryItem(
+                "Code Disk",
+                "A magnetic data disk.",
+                "The vault unlocks.",
+                new Room[]{ allowed },
+                blockage
+        );
+
+        item.setGame(game);
+        game.getInventory().addItem(item);
+
+        boolean used = item.use();
+
+        assertTrue(used);
+        assertEquals(0, blockage.getRequiredInteractionsToPass());
+        assertFalse(game.getInventory().getItems().contains(item));
+    }
+
+    @Test
+    void testUseFailsInWrongRoom() {
+        Room wrongRoom = game.getRooms().get(1);
+        Blockage blockage = new Blockage("Panel", 1);
+
+        InventoryItem item = new InventoryItem(
+                "Battery",
+                "A high-voltage battery.",
+                "You insert the battery.",
+                new Room[]{ wrongRoom },
+                blockage
+        );
+
+        item.setGame(game);
+        game.getInventory().addItem(item);
+
+        boolean result = item.use();
+
+        assertFalse(result);
+        assertEquals(1, blockage.getRequiredInteractionsToPass());
+        assertTrue(game.getInventory().getItems().contains(item));
+    }
+}

+ 100 - 0
src/test/java/eu/oschl/textadventure/objects/WeaponTest.java

@@ -0,0 +1,100 @@
+package eu.oschl.textadventure.objects;
+
+import eu.oschl.textadventure.BaseGameTest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests for the Weapon class.
+ *
+ * @author Ondřej Schlaichert
+ */
+class WeaponTest extends BaseGameTest {
+    @Test
+    void testConstructorInitializesFields() {
+        Weapon weapon = new Weapon(
+                "Axe",
+                "A brutal battle axe.",
+                "You swing the axe with rage.",
+                15
+        );
+
+        assertEquals("Axe", weapon.getName());
+        assertEquals("A brutal battle axe.", weapon.getDescription());
+        assertEquals("You swing the axe with rage.", weapon.getAttackText());
+        assertEquals(15, weapon.getDamage());
+    }
+
+    @Test
+    void testPickUpSucceedsWhenNoWeaponAndRoomUnblocked() {
+        Weapon weapon = new Weapon(
+                "Sword",
+                "A sharp sword.",
+                "You slash cleanly.",
+                10
+        );
+        game.getCurrentRoom().addObject(weapon);
+        weapon.setGame(game);
+
+        boolean picked = weapon.pickUp();
+
+        assertTrue(picked);
+        assertEquals(weapon, game.getInventory().getWeapon().orElse(null));
+        assertFalse(game.getCurrentRoom().getObjects().contains(weapon));
+    }
+
+    @Test
+    void testPickUpFailsIfRoomBlockedByEnemy() {
+        game.setCurrentRoom(game.getRooms().get(1));
+
+        Weapon weapon = new Weapon(
+                "Knife",
+                "A tiny knife.",
+                "You stab weakly.",
+                2
+        );
+        game.getCurrentRoom().addObject(weapon);
+        weapon.setGame(game);
+
+        boolean picked = weapon.pickUp();
+
+        assertFalse(picked);
+        assertFalse(game.getInventory().getWeapon().isPresent());
+    }
+
+    @Test
+    void testPickUpFailsIfWeakerThanCurrentWeapon() {
+        Weapon strong = new Weapon("Claymore", "Two-handed blade", "You cleave mightily.", 20);
+        Weapon weak = new Weapon("Dagger", "Rusty dagger", "You poke pathetically.", 5);
+
+        strong.setGame(game);
+        weak.setGame(game);
+
+        game.getInventory().setWeapon(strong);
+        game.getCurrentRoom().addObject(weak);
+
+        boolean picked = weak.pickUp();
+
+        assertFalse(picked);
+        assertEquals(strong, game.getInventory().getWeapon().orElse(null));
+    }
+
+    @Test
+    void testPickUpReplacesWeakerWeapon() {
+        Weapon weak = new Weapon("Stick", "A simple stick", "You bop someone with it.", 2);
+        Weapon stronger = new Weapon("Hammer", "Heavy and deadly", "You smash hard.", 15);
+
+        weak.setGame(game);
+        stronger.setGame(game);
+
+        game.getInventory().setWeapon(weak);
+        game.getCurrentRoom().addObject(stronger);
+
+        boolean picked = stronger.pickUp();
+
+        assertTrue(picked);
+        assertEquals(stronger, game.getInventory().getWeapon().orElse(null));
+        assertFalse(game.getCurrentRoom().getObjects().contains(stronger));
+    }
+}