RSS Amplifier

The Intermediate Catch Event · Mar 26, 2026

Testing Inbound Webhooks With Camunda Process Test

0
Sign in to vote or save

Stefan Schultz · The Intermediate Catch Event

Connector Validation (AI, 2026)

In one of my last articles, I wrote about payload validation for inbound webhooks. The model can reject bad payloads, check values with FEEL, and shape the data before the process continues. That is useful, but only half the story. At some point you need to prove that the webhook really works when the connector runtime is up and the process is deployed.

That is the point of this article. I want to show how to verify the whole inbound path: the webhook is reachable, authentication works, the payload is accepted or rejected as expected, the optional response looks right, and the process really starts or continues.

The setup is simpler than it sounds. Start the connector runtime next to the engine, point an HTTP client at the runtime address, wait until the webhook endpoint exists, then call it like a real consumer would.

If the real entry point is a webhook, starting the instance directly through CamundaClient is not enough. It skips the exact parts that tend to break.

The main things I want to verify are:

  • the webhook endpoint exists and is reachable.

  • the auth header is required and accepted.

  • the payload validation behaves as expected.

  • the optional response body contains the data I need.

  • the process starts or continues after the inbound connector fired.

Typical failures sit right there:

  • the webhook doesn’t exist.

  • the auth token is missing or wrong.

  • a FEEL check rejects a payload that used to pass.

That is why I like testing the webhook through HTTP. It keeps the test close to the real runtime path, without needing a full external environment.

For this setup, I want three things in every test:

  • the process engine

  • the connector runtime

  • a tiny HTTP helper that knows how to call the webhook

Test Setup in Camunda

Camunda Process Test already gives us the first two pieces. With SpringBoot, the shared base class can hold the rest.

If you prefer file based config, the same connector setup can live in src/test/resources/application.yaml.

And if you already package your connector runtime as a Spring Boot app, use that same app in the test. That keeps the test setup close to the real runtime behavior. The only thing I swap is the secret values.

Once the base class exists, the actual tests get small.

The first test covers the happy path. It waits for the route, starts the process through the webhook, and reads the optional instance key from the response.

This example assumes your webhook response expression returns the processInstanceKey in correlation. If that field is not part of the response, startProcessViaWebhook(...) returns Optional.empty(). That is why the return type is optional. Once you have the key, you can use your regular process assertions or search API to inspect the instance in more detail.

The next useful test is the negative auth case.

This is a cheap test, but it covers a real production risk. Someone changes the auth setup, or the token header is configured differently than expected, and suddenly the webhook is either too open or unusable.

The third test covers the callback case. Sometimes the webhook does not start a new instance. It continues an existing one that is waiting for external input. In that case I still use CamundaClient, but only to move the instance into the waiting state. The continuation itself still happens through the webhook.

In this case the instance key comes from startProcess(...), because the webhook is only used for the continuation step. After the callback, assert the completed path or variables with the same process assertion style you already use in the rest of your test suite.

That is the split I would keep:

  • use HTTP for the real webhook interaction.

  • use CamundaClient only when you need to prepare state before the callback.

  • return a process instance key where you can.

  • optionally, you can query for the instance key by using a ProcessInstanceSearchRequest.

If you already have complex FEEL expressions in your webhook, this is also the place to prove it. Send one payload that should pass and one that should fail. Then check both the response and the process path.

There is one current detail that is worth calling out. Right now, an inbound webhook can effectively behave in different ways:

  • as a message start event

  • as a none start event

The difference is whether the inbound webhook connector has a message attached to it or not. In my setup, getting the none start variant meant manually deleting the attached message event definition from the BPMN Xml. There is no visible way in the Web Modeler to do it.

Why does that matter? Because the returned correlation data is different.

With the none start variant, the response can include the processInstanceKey through the correlation object. That is useful when you want to follow the created instance directly from the webhook response.

With the message start variant, the response gives you the message correlation data, not the process instance key. In practice that means you get a messageKey, which is less useful when you want to inspect the created instance right away. You need to look up the started instance yourself.

So if your test needs to assert on the created process instance through the webhook response itself, the plain start variant is currently the better fit. I would treat this as current behavior, not as a permanent rule. Camunda may improve that later.

If you build validation logic into inbound webhooks, test the webhook itself. Do not bypass the route and then assume the rest will work.

The setup I would start with is:

  • start the engine and connector runtime together.

  • deploy the process with the real inbound webhook.

  • wait until the webhook route exists.

  • trigger it through a small HTTP helper.

  • inspect the (optional) response body.

The best practices I would keep are:

  • keep webhook related calls in a shared base class for others to use.

  • reuse production secret names (not values) in tests.

  • test both accepted and rejected payloads.

  • use the CamundaClient only to reach a waiting state before a webhook callback.

  • if you need the created instance key in the response, prefer the plain start variant for now.

That gives you a practical way to verify the webhook behavior you modeled, not just describe it.

No posts

Read the original on theintermediatecatchevent.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.