Skip to main content
World tests operate on a Hytale world instance, letting you spawn entities, place blocks, move objects, and verify world state. The WorldTestContext provides direct access to the world, its ECS store, block operations, and tick-waiting primitives.

@WorldTest

Annotate a method with @WorldTest to receive a WorldTestContext. Tests are automatically tagged with "integration" and scheduled on the world thread.
import com.frotty27.hrtk.api.annotation.WorldTest;
import com.frotty27.hrtk.api.context.WorldTestContext;

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

Specifying a world

@WorldTest(world = "my_custom_world")
void testInCustomWorld(WorldTestContext ctx) {
    // ctx.getWorld() returns the "my_custom_world" instance
}

WorldTestContext Methods

CategoryMethodDescription
WorldgetWorld()Get the Hytale World object
StoregetStore()Get the entity store
getCommandBuffer()Get a command buffer for deferred ops
flush()Execute deferred command buffer operations
BlockssetBlock(x, y, z, typeId)Set a block at coordinates
getBlock(x, y, z)Get the block type ID at coordinates
fillRegion(x1, y1, z1, x2, y2, z2, typeId)Fill a region with blocks
EntitiesspawnEntity(typeId)Spawn entity at origin
spawnEntity(typeId, x, y, z)Spawn entity at position
putComponent(ref, type, comp)Attach component to entity
removeComponent(ref, type)Remove component from entity
entityExists(ref)Check if reference is still valid
despawn(ref)Remove entity from world
PositiongetPosition(ref)Get entity position as [x, y, z]
setPosition(ref, x, y, z)Set entity position
TickswaitTicks(n)Block until N ticks elapse
waitTicksAsync(n)Non-blocking tick wait
awaitCondition(supplier, maxTicks)Poll each tick until non-null
QueriesfindEntities(componentType)Find entities with component
countEntities(componentType)Count entities with component
getComponent(ref, type)Get component (null if absent)
hasComponent(ref, type)Check if entity has component

WorldAssert Methods

MethodDescription
assertBlockAt(world, x, y, z, typeId)Assert block at position is expected type
assertBlockNotAt(world, x, y, z, typeId)Assert block is NOT the given type
assertEntityInWorld(world, ref)Assert entity exists in world
assertWorldExists(worldName)Assert a named world exists

Examples

@WorldTest
void entitySpawnsAtCorrectPosition(WorldTestContext ctx) {
    Object entity = ctx.spawnEntity("hytale:kweebec", 10, 64, 20);
    ctx.waitTicks(1);

    double[] pos = ctx.getPosition(entity);
    HytaleAssert.assertNotNull(pos);
    HytaleAssert.assertEquals(10.0, pos[0], 0.5);
    HytaleAssert.assertEquals(64.0, pos[1], 0.5);
    HytaleAssert.assertEquals(20.0, pos[2], 0.5);
}
@WorldTest
void blockPlacementWorks(WorldTestContext ctx) {
    ctx.setBlock(0, 64, 0, "hytale:stone");
    WorldAssert.assertBlockAt(ctx.getWorld(), 0, 64, 0, "hytale:stone");
    WorldAssert.assertBlockNotAt(ctx.getWorld(), 0, 64, 0, "hytale:air");
}
@WorldTest
void fillRegionPlacesBlocks(WorldTestContext ctx) {
    ctx.fillRegion(0, 60, 0, 10, 60, 10, "hytale:grass");

    // Spot check corners
    WorldAssert.assertBlockAt(ctx.getWorld(), 0, 60, 0, "hytale:grass");
    WorldAssert.assertBlockAt(ctx.getWorld(), 10, 60, 10, "hytale:grass");
    WorldAssert.assertBlockAt(ctx.getWorld(), 5, 60, 5, "hytale:grass");
}
@WorldTest
void despawnedEntityNoLongerExists(WorldTestContext ctx) {
    Object entity = ctx.spawnEntity("hytale:kweebec", 0, 64, 0);
    ctx.waitTicks(1);
    HytaleAssert.assertTrue(ctx.entityExists(entity));

    ctx.despawn(entity);
    ctx.waitTicks(1);
    // Entity reference should no longer be valid
}

Isolation for World Tests

World tests that modify blocks or spawn entities should use IsolationStrategy.DEDICATED_WORLD to avoid polluting the live server:
@HytaleSuite(value = "Block Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
@Tag("integration")
public class BlockTests {
    // Tests run in a temporary void world that is destroyed after the suite
}
See Isolation: DEDICATED_WORLD for details.

Next Steps