Skip to main content
IsolationStrategy.DEDICATED_WORLD creates a temporary void world for your suite, runs all tests inside it, and destroys it when the suite finishes. This provides the strongest isolation — nothing from your tests can affect the live server’s worlds.

When to Use

  • Tests that place or break blocks
  • Tests that spawn entities and need a clean environment
  • Integration tests and flow tests (spawn -> combat -> loot)
  • Any test that needs a predictable, empty world

How It Works

1

Before Suite

HRTK calls TestWorldManager.getOrCreateTestWorld(suiteId) to create a void world. The world has no terrain, no entities, and no blocks — a blank canvas.
2

Test Execution

Your @WorldTest and @FlowTest methods receive a WorldTestContext bound to the temporary world. You can spawn entities, place blocks, and modify state freely.
3

After Suite

HRTK calls TestWorldManager.cleanupTestWorld(suiteId) to destroy the world and all its contents. No trace remains.

Usage

import com.frotty27.hrtk.api.lifecycle.IsolationStrategy;

@HytaleSuite(value = "Block Placement Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
@Tag("integration")
public class BlockPlacementTests {

    @WorldTest
    void placeAndVerifyBlock(WorldTestContext ctx) {
        ctx.setBlock(0, 64, 0, "hytale:stone");
        WorldAssert.assertBlockAt(ctx.getWorld(), 0, 64, 0, "hytale:stone");
    }

    @WorldTest
    void fillRegionAndVerify(WorldTestContext ctx) {
        ctx.fillRegion(0, 60, 0, 10, 60, 10, "hytale:grass");
        WorldAssert.assertBlockAt(ctx.getWorld(), 5, 60, 5, "hytale:grass");
    }

    @WorldTest
    void worldStartsEmpty(WorldTestContext ctx) {
        // Dedicated world is void -- no blocks anywhere
        String block = ctx.getBlock(0, 64, 0);
        // Should be air or null in a void world
    }
}

Entity Spawning in Dedicated Worlds

Dedicated worlds are the safest place to spawn test entities. They will not collide with existing live-world entities, and cleanup is automatic.
@HytaleSuite(value = "Combat Flow Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
@Tag("combat")
public class CombatFlowTests {

    @FlowTest(timeoutTicks = 200)
    void spawnFightAndVerifyLoot(WorldTestContext ctx) {
        // Spawn in a clean world
        Object attacker = ctx.spawnEntity("hytale:kweebec", 0, 64, 0);
        Object target = ctx.spawnEntity("hytale:trork", 5, 64, 0);
        ctx.waitTicks(1);

        CombatAssert.assertAlive(ctx.getStore(), attacker);
        CombatAssert.assertAlive(ctx.getStore(), target);

        // ... fight logic ...
    }
}

Fallback Behavior

If HRTK cannot create a dedicated world (e.g., due to server configuration or resource limits), it logs a warning and falls back to running against live state:
HRTK: Failed to create test world -- running against live state
If the dedicated world creation fails, your tests run with NONE isolation semantics. Any mutations will affect the live server. Monitor the console for fallback warnings.

Performance

Creating and destroying a world has significant overhead compared to NONE or SNAPSHOT. This cost is paid once per suite, not per test. For suites with many tests, the per-test amortized cost is small.
OperationTypical Cost
World creation50-200ms
World destruction10-50ms
Per-test executionSame as NONE
Group your world-mutating tests into a small number of suites to minimize the number of world creates/destroys. Each suite gets its own dedicated world.

Complete Example

@HytaleSuite(value = "Full Integration Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
@Tag("integration")
public class FullIntegrationTests {

    @WorldTest
    @Order(1)
    void canSpawnEntity(WorldTestContext ctx) {
        Object entity = ctx.spawnEntity("hytale:kweebec", 0, 64, 0);
        ctx.waitTicks(1);
        HytaleAssert.assertTrue(ctx.entityExists(entity));
    }

    @WorldTest
    @Order(2)
    void canPlaceBlock(WorldTestContext ctx) {
        ctx.setBlock(0, 63, 0, "hytale:stone");
        WorldAssert.assertBlockAt(ctx.getWorld(), 0, 63, 0, "hytale:stone");
    }

    @WorldTest
    @Order(3)
    void canPositionEntity(WorldTestContext ctx) {
        Object entity = ctx.spawnEntity("hytale:kweebec", 0, 64, 0);
        ctx.waitTicks(1);

        ctx.setPosition(entity, 100, 64, 100);
        ctx.waitTicks(1);

        double[] pos = ctx.getPosition(entity);
        HytaleAssert.assertEquals(100.0, pos[0], 1.0);
    }
}

Next Steps