Processor Testing
Processor mode tests one Processor lambda in complete isolation: no PipeliteContext, no endpoints, no flow — just the input you provide and the processor’s effect on it, evaluated synchronously.
Use it as the default way to unit-test the business logic of a single step, the same way you would unit-test a plain function.
A basic test
given(inputPayload(Map.of("price", 100)))
.when(process(myProcessor))
.then(isSuccess(), payloadEquals(Map.of("price", 110)));
given(…) prepares the exchange that will be handed to the processor; process(…) invokes it; then(…) verifies both the outcome of the invocation and the resulting exchange state.
Preparing the input
Any combination of headers and an input payload can be supplied, in any order:
given(
header("Source-System", "Legacy-API"),
header("X-Tenant", "acme"),
inputPayload(new Order("ORD-001")))
.when(process(orderProcessor))
.then(isSuccess());
Verifying success and failure
A processor either completes normally or throws. Both outcomes are first-class assertions:
@Test
void completesSuccessfully() {
given(inputPayload("hello"))
.when(process((exchange, contribution) -> exchange.setOutputPayload("world")))
.then(isSuccess(), payloadEquals("world"));
}
@Test
void propagatesFailure() {
RuntimeException expected = new RuntimeException("boom");
given(inputPayload("input"))
.when(process((exchange, contribution) -> { throw expected; }))
.then(isFailure(), failureCause(expected));
}
A thrown RuntimeException never escapes the test as an exception — it is captured and exposed as a fact you assert on with isFailure() and, if needed, matched precisely with failureCause(…).
Verifying explicit stop
Some processors signal "stop here" via stopExecution() on the contribution passed to them, instead of returning an error. This is asserted the same way:
given(inputPayload("duplicate-id"))
.when(process((exchange, contribution) -> {
if (isDuplicate(exchange.getInputPayload())) {
contribution.stopExecution();
}
}))
.then(isExecutionStopped());
Asserting on headers and typed payloads
The same exchange-level expectations used for flows also apply here:
given(inputPayload("Alice"))
.when(process((exchange, contribution) ->
exchange.setOutputPayload("Hello, " + exchange.getInputPayload() + "!")))
.then(
headerEquals("X-Greeting-Language", "en"),
payloadAs(String.class, greeting -> assertThat(greeting).startsWith("Hello")));
payloadAs(…) is the bridge to AssertJ, JUnit, or any assertion library: it checks the payload’s type, then hands you the typed instance.
Reading the result directly
When it’s more convenient to assert with your own tooling than with then(…), ThenOperations also exposes the result directly:
ThenOperations result = given(inputPayload(42))
.when(process((exchange, contribution) ->
exchange.setOutputPayload(exchange.getInputPayloadAs(Integer.class) * 2)))
.then(isSuccess());
assertThat(result.getOutputPayloadAs(Integer.class)).isEqualTo(84);
For the complete list of preconditions and expectations available in processor mode, see the Appendix. To test multiple processors wired together end-to-end, move on to Flow Testing.