Skip to main content
When tests run inside a live server, they share state with the production environment. Isolation strategies control how much of that shared state is protected from test mutations. Choosing the right strategy is critical for test reliability and server safety.

The Three Strategies

StrategyProtectsCostBest For
NONENothingZero overheadRead-only tests, pure logic, assertions
SNAPSHOTECS store stateSnapshot + restore per suiteComponent mutation tests
DEDICATED_WORLDFull world stateWorld create + destroy per suiteBlock, spawn, and integration tests

Decision Flowchart

1

Does your test modify ECS components?

If no, use NONE. If yes, continue.
2

Does your test modify blocks or spawn entities?

If no, use SNAPSHOT. If yes, use DEDICATED_WORLD.

Side-by-Side Comparison

NONE

No protection. Tests see and modify live server state. Suite instantiation is the only boundary. Fast but risky for mutating tests.

SNAPSHOT

ECS state is captured before the suite and restored after. Components modified during tests are reverted. Blocks and spawned entities are NOT rolled back.

DEDICATED_WORLD

A temporary void world is created for the suite. All entities, blocks, and state are destroyed when the suite completes. Full isolation at the cost of world creation overhead.

Usage

Set the isolation strategy on @HytaleSuite:
// Default -- no isolation
@HytaleSuite("Pure Logic Tests")
public class PureLogicTests { }

// Snapshot -- ECS state rollback
@HytaleSuite(value = "Component Tests", isolation = IsolationStrategy.SNAPSHOT)
public class ComponentTests { }

// Dedicated world -- full isolation
@HytaleSuite(value = "World Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
public class WorldTests { }

When to Use Each

Use NONE when your tests:
  • Only read data, never write
  • Test pure functions or utility classes
  • Test codec round-trips (no server state involved)
  • Verify annotations, configuration, or metadata
@HytaleSuite("Math Utils Tests")
public class MathUtilsTests {
    @HytaleTest
    void testClamp() {
        HytaleAssert.assertEquals(5, MathUtils.clamp(10, 0, 5));
    }
}
Use SNAPSHOT when your tests:
  • Create entities and attach/remove components
  • Modify stat values or entity state
  • Need to revert changes after the suite without destroying the world
@HytaleSuite(value = "Stat Modifier Tests", isolation = IsolationStrategy.SNAPSHOT)
public class StatModifierTests {
    @EcsTest
    void testApplyModifier(EcsTestContext ctx) {
        Object ref = ctx.createEntity();
        // Modify ECS state -- will be rolled back after suite
    }
}
Use DEDICATED_WORLD when your tests:
  • Place or break blocks
  • Spawn and kill entities
  • Need a clean, predictable world state
  • Test multi-step flows (spawn -> modify -> verify -> cleanup)
@HytaleSuite(value = "Block Tests", isolation = IsolationStrategy.DEDICATED_WORLD)
public class BlockTests {
    @WorldTest
    void testBlockPlacement(WorldTestContext ctx) {
        ctx.setBlock(0, 64, 0, "hytale:stone");
        // Clean world -- no interference from existing blocks
    }
}
Using NONE for tests that mutate server state is dangerous. Changes made by your tests will persist after the test run, potentially affecting live gameplay or other test suites.

Next Steps