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>
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:
scenario.setupEnvironment()starts your infrastructure.- The
Consumer<TransitionBuilder>registers steps — no HTTP calls happen yet. - The state machine executes: POST runs once, GET retries until the assertion passes or the timeout expires.
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
- Core Concepts → Mental Model — understand the state machine
- Adapters → REST — full REST adapter reference
- Adapters → SSR — server-side rendered HTML adapter
- Patterns → Test Structure — how to organize tests well