Skip to main content

Getting Started — Java

Install

Add xceptoj dependencies to your test project:

// Gradle
testImplementation 'org.xcepto:xceptoj:VERSION'
testImplementation 'org.xcepto:xceptoj-http:VERSION' // shared HTTP abstractions
testImplementation 'org.xcepto:xceptoj-rest:VERSION' // REST (JSON) adapter
testImplementation 'org.xcepto:xceptoj-ssr:VERSION' // SSR adapter
<!-- Maven -->
<dependency>
<groupId>org.xcepto</groupId>
<artifactId>xceptoj</artifactId>
<version>VERSION</version>
<scope>test</scope>
</dependency>
note

xceptoj-http must be declared explicitly alongside xceptoj-rest or xceptoj-ssr if your code references types from that module directly (such as Promise or HttpMethodVerb). Gradle's implementation scope does not expose transitive dependencies.

Write a scenario

A Scenario specifies how to set up and tear down the system under test. Override setupEnvironment to start infrastructure and expose configuration:

public class MyScenario extends Scenario {
public int port;

@Override
public void setupEnvironment() throws XceptoScenarioResetException {
try {
// start your service, assign port
this.port = startMyService();
} catch (Exception e) {
throw new XceptoScenarioResetException("Failed to start service", e);
}
}

@Override
public void stopEnvironment() throws XceptoScenarioResetException {
stopMyService();
}
}

See Scenario for the full lifecycle.

Write your first test

Xcepto.given compiles adapter calls into a state machine and runs it. The Consumer<TransitionBuilder> is always the second argument:

@Test
void shipmentIsAccepted() throws Exception {
var scenario = new MyScenario();
var amount = 50;

Xcepto.given(scenario, builder -> {
var rest = new RestAdapterBuilder(builder)
.withBaseUrl(URI.create("http://localhost:" + scenario.port))
.withSerializer(new GsonSerializer())
.build();

rest.post("/shipment/accept")
.withRequestBody(() -> new AcceptShipmentRequest(amount))
.withResponseType(AcceptShipmentResponse.class)
.assertThatResponse((AcceptShipmentResponse r) -> r.amount == amount);

rest.get("/inventory/stock")
.assertSuccess()
.assertThatResponseContentString(
body -> body.contains("\"replenished\":true"));
});
}

What happens at runtime:

  1. scenario.setupEnvironment() starts your infrastructure.
  2. The Consumer<TransitionBuilder> registers steps — no HTTP calls happen yet.
  3. The state machine executes: POST runs once, GET retries until the assertion passes or the timeout expires.
  4. scenario.stopEnvironment() tears down infrastructure — always runs, even on failure.

Configure a timeout

var timeout = new TimeoutConfig(
Duration.ofSeconds(30), // total: covers setup + execution
Duration.ofSeconds(25)); // test: covers state machine only

Xcepto.given(scenario, builder -> {
// ...
}, timeout, Duration.ofMillis(100)); // 100ms poll interval

See Timeout & Failures.

Note on the Serializer

xceptoj does not bundle a JSON library. Implement the Serializer interface with your preferred library:

public class GsonSerializer implements Serializer {
private final Gson gson = new Gson();

@Override public String serialize(Object obj) { return gson.toJson(obj); }

@Override public <T> T deserialize(String json, Class<T> type) {
return gson.fromJson(json, type);
}
}

Next steps