Skip to content

Testing web endpoints

Fluxzero allows you to simulate and verify HTTP interactions as part of your test flows. Web requests can be tested like any other command, query, or event.

Here’s a complete test for a POST /games handler that accepts a JSON request and publishes a command:

@Test
void registerGame() {
testFixture
.whenPost("/games", "/game/game-details.json") // Simulates POST with payload
.expectResult(GameId.class) // Asserts a result is returned
.expectEvents(RegisterGame.class); // Asserts the applied update was published as an event
}

The corresponding handler is:

@HandlePost("/games")
CompletableFuture<GameId> addGame(GameDetails details) {
return Fluxzero.sendCommand(new RegisterGame(details));
}

As always, the .json file is automatically loaded from the classpath, allowing you to cleanly separate test data:

📄 /game/game-details.json

{
"title": "Legend of the Skylands",
"description": "An epic singleplayer adventure with puzzles and secrets.",
"releaseDate": "2025-11-12T00:00:00Z",
"tags": [
"adventure",
"puzzle",
"singleplayer"
]
}

You can test GET endpoints just as easily. This example first registers a game via POST /games, then fetches the list of all games via GET /games and checks the result:

@Test
void getGames() {
testFixture
.givenPost("/games", "/game/game-details.json") // Precondition: register a game
.whenGet("/games") // Perform GET request
.<List<Game>>expectResult(r -> r.size() == 1) // Assert one game is returned
.expectWebResponse(r -> r.getStatus() == 200); // Assert the status of the response
}

In Java, the explicit .<List<Game>> cast is needed because whenGet(...) alone does not expose a concrete generic result type to the fixture.

This corresponds to the following handler method:

@HandleGet
@Path("/games")
CompletableFuture<List<Game>> getGames(@QueryParam String term) {
return Fluxzero.query(new FindGames(term));
}

Fluxzero allows you to verify how your web endpoints handle exceptional scenarios. This includes asserting the exception type as well as inspecting the resulting HTTP status or body.

Here’s a test that triggers a 403 Forbidden error via IllegalCommandException:

@Test
void postReturnsError() {
testFixture
.whenPost("/error", "body") // Simulate POST request
.expectExceptionalResult(IllegalCommandException.class) // Assert thrown exception
.expectWebResponse(r -> r.getStatus() == 403); // Assert HTTP 403 response
}

The corresponding handler might look like:

@HandlePost("/error")
void postForError(String body) {
throw new IllegalCommandException("error: " + body);
}

Fluxzero supports placeholder substitution in endpoint paths based on results from earlier steps.

  • The result of the first when...() step is saved after .andThen() is called.
  • Later paths like /games/{gameId}/buy will have {gameId} filled using the .toString() value of the previous result.
  • All results are tracked in order and substituted by position, not type.
testFixture.whenPost("/games", "/game/game-details.json") // returns gameId
.andThen()
.whenPost("/games/{gameId}/buy") // uses gameId, returns orderId
.andThen()
.whenPost("/games/{gameId}/refund/{orderId}"); // uses both

© 2026 Fluxzero