Moving Flowable process tests from JUnit 4 to JUnit 5

If your Flowable process test suite still runs on JUnit 3 or 4, Flowable 8.0.0 will not run it. This page explains how to move the tests to JUnit 5 before the engine upgrade and keep them green while you do.

On this page

Why Flowable process tests must move to JUnit 5 before Flowable 8

If your Flowable application still runs its process tests on JUnit 3 or JUnit 4, those tests have to move to JUnit 5 before or alongside the upgrade to Flowable 8. Flowable 8.0.0 removed JUnit 3 and 4 support and supports JUnit 5 (Jupiter) exclusively, according to the Flowable 8.0.0 release notes. A suite left on the old runners will not compile or run against the new engine, so the test rewrite is a gating item for the upgrade, not a cleanup task that can wait.

The scope is wider than renaming imports. It covers every test class that extends a Flowable base class or uses the JUnit 4 runner, the setup that relies on the old rules and lifecycle methods, and every @Deployment annotation that loads BPMN, CMMN or DMN resources before a test. Your team should inventory those classes and base classes first and confirm which ones your build actually compiles and runs today. Treat this as its own work package, separate from the Spring Boot 4 and Jackson 3 changes. Test failures caused by a changed Spring context are hard to separate from failures caused by a changed test harness if both move in one step, so keeping the test migration distinct makes each regression easier to trace.

Flowable deprecated JUnit 3 and 4 support in 7.2.0, which gave teams a release window to start the rewrite while the old tests still ran on a supported engine. Teams that have not started should confirm their current Flowable version, list every test that depends on the deprecated support, and agree with the upgrade owner whether the test rewrite lands in the same branch as the engine change or in a prior release.

What changes in the test suite for Flowable 8

This table compares how the test suite behaves on Flowable 7.x and Flowable 8.0.0, row by row, so you can see what breaks and what to change. Read each row as a question: what changed, what it does to your existing tests, and what your team needs to do before the upgrade. The main takeaway is that JUnit 3 and 4 tests will not survive the move to Flowable 8 unchanged.

ChangeImpact on the suiteAction needed
JUnit 3 and 4 support deprecated in 7.2.0Suites still on JUnit 3 or 4 were flagged for removal one release before the change landed, so warnings on 7.2.0 signal work that cannot be deferred.Inventory every test class that imports JUnit 3 or 4 runners or base classes, and schedule the rewrite before the 8.0.0 branch is opened.
JUnit 3 and 4 support removed in 8.0.0Tests that depend on JUnit 3 or 4 support fail to compile or fail to run against Flowable 8.0.0 because the support is gone.Rewrite affected classes to JUnit 5 (Jupiter) before upgrading the engine dependency, and confirm the rewrite passes on the current 7.x version first.
JUnit 5 (Jupiter) as the only supported modelFlowable 8 test support targets Jupiter exclusively, so the JUnit 5 Vintage engine or mixed runners are not a supported path for Flowable tests.Confirm the test dependencies, build plugins and IDE runners use the Jupiter engine, and ask your Flowable contact whether any Vintage bridge is supported.
FlowableTest annotationTest classes annotated with FlowableTest receive the engine test support through Jupiter, replacing hand-built engine setup in base classes.Replace custom setup or teardown base classes with the annotation where the existing behavior allows it, and review any test that relied on shared static engine state.
FlowableExtension registrationTeams that cannot or prefer not to use the annotation register FlowableExtension explicitly, which changes how the engine lifecycle is attached to each test.Pick one registration style per module, apply it consistently, and check that engine start and stop order still matches the original suite.
@Deployment resources before and after each testProcess resources named in @Deployment are deployed before each test and deleted afterwards, so tests that assumed deployments persisted across methods will change behavior.Confirm each test's BPMN and CMMN or DMN resource paths still resolve, and move any setup that needs to span several tests into the test itself.

How FlowableTest, FlowableExtension and @Deployment fit together

A JUnit 5 Flowable test gets its engine in one of two ways: annotate the test class with @FlowableTest, or register the FlowableExtension on the class with @ExtendWith. Either route starts a process engine for the test and hands it to the test through injected services such as the runtime and task services. The key decision for your migration is that the JUnit 4 pattern of rules and base classes has no direct equivalent to copy line by line, so each suite needs its engine lifecycle mapped to one of these two entry points. Confirm the exact annotation names, injection options and configuration attributes against the Flowable API docs for the version you are targeting, because the wiring differs between releases and should not be reconstructed from memory of Flowable 6 or 7 tests.

The @Deployment annotation sits on the test method or class and tells the engine which BPMN resources to deploy before each test. The engine deletes those deployments after the test finishes, so a clean deployment is the default for every test. This is the behavior to plan around. Tests that depended on a process definition deployed by an earlier test, on a static field holding a value from a prior run, or on rows left in the database will fail or pass for the wrong reason once the suite runs in a different order or in isolation. During the rewrite, list every test that reads state it did not set up itself, move that setup into the test or into a shared fixture, and run the suite in random order to expose hidden dependencies. Your team should also decide who owns the list of resource paths, since a renamed BPMN file will break the annotation silently until the test runs.

What to inventory and set up before rewriting tests

Before any test is rewritten, you need a complete picture of what the suite depends on and a baseline that passes on the Flowable version you run today. The cards below cover the items that most often cause a stalled or misleading migration, in the order a team usually works through them.

Inventory JUnit 3 and 4 usage

List every test class and shared base class that imports junit.framework or org.junit, and note which ones extend a Flowable test case or use a custom runner. Search for @Rule, @ClassRule, @RunWith, and setUp or tearDown methods, because each one maps to a different JUnit 5 mechanism. Flowable 8.0.0 removed JUnit 3 and 4 support, so any class you miss will fail to compile after the upgrade. Record the count per module so you can estimate the rewrite and track progress.

Green baseline on current version

Run the full process test suite on your current Flowable version and record which tests pass before you change anything. Any test that already fails needs a documented reason, or it will hide migration regressions later. Keep the baseline output so you can compare test names, counts and assertions after the rewrite. Confirm that the same Java and Spring versions are used in the baseline run as in production.

Test database setup and cleanup

Confirm which database each test run uses, whether that is H2 for local runs or a containerized PostgreSQL, MySQL or another supported type for integration runs. Check how the schema is created and dropped between tests, and whether tests share data that another test depends on. Shared state is the most common source of intermittent failures once tests move to a new lifecycle. Note any database-specific SQL in the tests.

Deployment resource paths

List every BPMN, CMMN and DMN resource referenced by @Deployment and confirm each path still resolves from the test classpath. Check for resources that are shared between classes, since the annotation deploys and deletes them around each test and duplicate deployments can change results. Verify that resource names match the process keys your assertions use. Record any test that loads resources programmatically, because it will need a separate review.

Custom rules and runners

Identify every custom @Rule, @ClassRule, @RunWith runner, or helper that wraps the engine lifecycle, such as a custom engine builder or a fixture that starts the engine manually. Each of these needs an equivalent JUnit 5 extension, a @FlowableTest configuration, or a plain setup method. Document what each one does before replacing it, especially around clock control, job execution and identity setup. Behavior that was hidden in a runner is often the first thing missing after the move.

CI pipeline changes

Check how your build tool runs tests, since JUnit 5 requires the Jupiter engine on the test runtime and some pipelines select tests by the old runner or by naming pattern. Confirm that test reports and coverage tools still read results from the new engine. Plan to run the old and new test sets side by side until the rewritten suite matches the baseline. Agree with the team which build must pass before the Flowable 8 branch merges.

How to convert the suite and keep it green

The sequence keeps the suite passing at every stage by changing one thing at a time: the test framework first, then the engine version, so any failure has a single identifiable cause. Each step ends with a commit you can return to.

  1. Record a green baseline on the current version

    Before touching any test code, run the full Flowable process test suite against the current engine version and confirm it passes on the branch you will convert. The team lead or a senior engineer owns this step. Tag the commit and record the test count, the skipped tests and the build command so later runs can be compared against the same numbers. Done means a repeatable run from a clean checkout with no failures, and a tagged commit that serves as the rollback point for the entire project. If the baseline is already flaky, fix or quarantine those tests here, because a flaky baseline makes every later step impossible to judge.

  2. Convert one pilot test class and its base classes

    Choose one test class that covers a representative mix of deployments, variables and assertions, and convert it together with any abstract base class it extends. Replace JUnit 3 or 4 lifecycle annotations and runners with the JUnit Jupiter equivalents, and move the test to the Flowable test support described in the Flowable API documentation, either the FlowableTest annotation or the FlowableExtension registration. Confirm that @Deployment still points at the same BPMN resources. Done means the pilot class passes on the current engine with no changes to the process models and no assertions weakened. Commit the pilot alone so the team can review the pattern before it is copied.

  3. Convert the remaining tests in batches

    Divide the rest of the suite into batches grouped by package or by shared base class, not by file count, so that a batch shares one set of conventions. Engineers convert each batch following the pilot pattern and run the full suite on the current engine before committing. Review each diff for changed assertions, since a converted test that passes only because an assertion was loosened hides a defect. Done means every batch is a separate commit that passes the full suite. If a batch breaks, revert only that commit and fix it in isolation.

  4. Run the converted suite on the current engine after each batch

    After each batch merges, run the complete suite on the unchanged current engine and compare the results to the baseline recorded in the first step. The check is that the test count matches, no test was silently dropped or disabled, and nothing that was green has turned red. Quality or QA engineers can own this comparison with a short checklist. Done means a recorded run for each batch with the same or higher passing count. Keep these run records with the commit hashes so any later regression can be traced to a specific batch.

  5. Switch the engine to Flowable 8 and fix only what fails

    Once every test runs on JUnit 5 under the current engine, change the Flowable dependency to version 8 as a separate commit, along with the Spring and Java changes the Flowable 8 release notes require for your application. Fix only the failures this change produces, and record each fix against its cause, such as Jackson 3 changes or Spring Framework 7 configuration. Do not refactor tests during this step. Done means the full suite passes on Flowable 8, and the commit history shows that the framework conversion and the engine upgrade are separate, reviewable changes. Confirm your Java and Spring baseline against the Flowable 8.0.0 release notes before starting this step.

  6. Remove JUnit 4 dependencies from the build

    Once the suite is green on Flowable 8, remove the JUnit 4 and vintage engine dependencies from the build files, and delete any leftover imports, runners or rules that the conversion did not touch. Search the codebase for org.junit.Test and similar JUnit 4 imports to confirm none remain. Done means the dependency tree contains only JUnit Jupiter for these tests, the build passes from a clean checkout, and the final commit is tagged. Keep the tag from step one and the final tag together in your release notes so the reviewers can see the full change set.

Questions teams ask before moving Flowable tests to JUnit 5

Can our own team move Flowable process tests to JUnit 5 without a partner?

Yes, in most codebases an in-house team can do the move, provided its engineers already know JUnit and the Flowable test setup. The work is mostly mechanical: replacing JUnit 4 runners and rules with JUnit 5 annotations, switching to @FlowableTest or FlowableExtension, and checking that each @Deployment resource still loads. The effort rises when the suite has many custom rules, shared base classes or tests that depend on execution order. Ask a partner, if you use one, for a fixed-scope written plan that lists which test classes and custom rules are in scope, so the work can be compared with your own estimate.

What drives the effort of rewriting a Flowable test suite?

The main drivers are the number of test classes, how much of the suite depends on JUnit 4 features, and how many tests share setup through base classes. Teams with custom TestRule implementations, @Rule fields or @Before and @After chains usually spend the most time, because each one needs a JUnit 5 equivalent. Deployment patterns also matter: tests that deploy many BPMN, CMMN or DMN resources need each @Deployment reference checked against the resource paths. Ask for a quote that counts test classes by category, lists custom rules, and states how tests will be verified before and after the change.

Must the test migration happen before the Flowable 8 engine upgrade?

Yes, the test migration should come first. Flowable 8.0.0 removed JUnit 3 and JUnit 4 support, so a suite still on those frameworks will not compile or run against the upgraded engine. The practical sequence is to move tests to JUnit 5 while the engine is still on a version where the old tests pass, confirm the suite is green, and then upgrade the engine and Spring baseline. Check the Flowable 8.0.0 release notes for the exact support changes that apply to your version, and confirm with your own build tooling which JUnit artifacts your project pulls in.

How do we keep Flowable tests green while we migrate them?

Move tests in small batches and run the full suite after each batch, so a failure points to a specific change. Start with a baseline run that records which tests pass today, including any that are already flaky, so later failures are not blamed on the move. Convert shared infrastructure, such as base classes and extensions, before the individual test classes that depend on it. Keep the deployment resources unchanged where possible, and compare the deployed definition keys before and after each batch. Engineers should also confirm that test database state is reset between tests, since changed lifecycle timing can expose state leaks.

What should we do with custom JUnit 4 rules and runners?

Each custom rule or runner needs an explicit decision: rewrite it as a JUnit 5 extension, move its logic into a shared setup method, or retire it if the Flowable test annotations already cover the same need. Rules that manage the engine lifecycle are the most important to review, because FlowableExtension and @FlowableTest take over part of that job. Document the behavior each custom rule provides today and write a test that shows the same behavior after the change. Confirm the exact registration and parameter behavior in the Flowable API documentation before you remove anything.

What does the migration need from our engineering team?

The work needs engineers who own the test code, can review BPMN, CMMN and DMN deployments, and can run the build in a stable environment. Plan for a person who understands the business process models, since a test that deploys the wrong resource can pass for the wrong reason. Ask the team to agree on a naming and structure convention for tests, and to give reviewers time to check changed assertions rather than only compiling changes. Your own CI pipeline should run the suite on every batch, so the team can see regressions as they occur.

Is there a cost or license issue with changing the test framework?

Flowable is licensed under Apache 2.0, and moving tests to JUnit 5 does not change the engine license. The cost comes from engineering time and review, and from any test infrastructure that must be updated, such as build plugins and CI images. Costs recur only if the suite keeps changing, so the one-time migration cost is the main item. When requesting a quote, ask for the work broken into test inventory, rule conversion, batch verification and handover, and ask who maintains the suite after the engagement ends.

What makes the test migration longer or shorter

This table compares the factors that move the JUnit 4 to JUnit 5 effort for Flowable test suites up or down. Read each row as a question to answer about your own suite before estimating, because a small number of classes with heavy custom runner logic can cost more than a large, uniform suite. The main takeaway is that custom JUnit 4 rules, runners and shared base classes usually decide the effort more than raw test count.

DriverEffect on effortWhat to check first
Number of test classesEffort grows with the count, but mechanical annotation changes are quick to repeat across a uniform suiteCount classes that extend Flowable test base classes or use the Flowable test rule, and group them by pattern
Custom JUnit 4 rules or runnersCustom rules and runners have no direct equivalent and need redesign as JUnit 5 extensions, often the largest share of workList every @Rule, @ClassRule and @RunWith usage and identify which ones wrap engine setup or teardown
Depth of shared base classesDeep inheritance chains hide engine configuration, so changes ripple across many tests and need careful reviewMap the base class hierarchy and note which classes set up the process engine or database
Reliance on @Deployment across testsTests that share deployments or depend on ordering must be untangled so each test deploys its own resourcesCheck whether tests rely on resources deployed by other tests or on a previous test's state
Size and speed of the test databaseA large or slow database extends the time needed to run the suite repeatedly while the migration proceedsMeasure current suite runtime and confirm which database type the tests use, such as H2 or a containerized server
Number of Flowable modules in useEach engine or REST module in use adds test configuration and dependency updates, especially when Spring Boot starters are involvedList the BPMN, CMMN, DMN and REST modules on the test classpath and their Spring Boot starter usage

Keeping the suite green while the engine changes

Convert the test framework first and leave the engine alone, then upgrade Flowable as a separate step. The reason is attribution: if the suite goes red during a combined change, the team cannot tell whether a failing @Deployment resource, a changed assertion or an engine behavior caused it. In stage one, the existing Flowable 7.x engine stays in place, the JUnit 3 or 4 classes move to JUnit 5 Jupiter, and every test must pass on the old engine before anything else changes. Stage two then upgrades the engine to Flowable 8.0.0 with the test code already stable, so any new failure points at the engine, the Spring Boot 4 baseline or the Jackson 3 default. Confirm with your own build which Flowable version and Spring Boot line the current suite runs on before you start, since the stage boundary depends on that baseline.

The main risk in stage one is masking real regressions. When a converted test fails, it is tempting to loosen an assertion, swap an exact process variable check for a null check, or delete a step that no longer compiles. Each of those edits can hide a defect the old suite was catching. Set a rule that conversion commits change only the framework: annotations, lifecycle hooks, imports and the extension registration. Any assertion change needs its own commit with a written reason, reviewed separately. Before converting, record the count of passing tests and the assertions on process end states, history entries and task lists, so you can confirm that the converted suite still checks the same things. Ask your team to name which tests cover money-moving or approval paths and treat those as non-negotiable.

How DeployOpen scopes and delivers a Flowable test migration

DeployOpen plans and delivers the move of Flowable process test suites from JUnit 4 to JUnit 5 as a written, fixed-scope piece of work. The work runs before the Flowable 8 upgrade so that the test suite can prove the engine and application behave the same way throughout the change.

How we scope

  • Inventory every test class that uses JUnit 3 or 4 runners, rules or base classes in your Flowable codebase
  • Record which tests depend on @Deployment resources, shared engine setup or custom test configuration
  • Agree in writing which suites move, which are rewritten and which are retired
  • Confirm the target Flowable version, Spring Boot version and build tooling the tests must run on
  • Set the acceptance criteria, including which pass results must hold before the upgrade starts

How we build

  • Convert test classes to JUnit 5 using FlowableTest or FlowableExtension, one module at a time
  • Keep each converted suite green on the current engine version before changing the next module
  • Move @Deployment resource paths and process definitions so each test deploys only what it needs
  • Replace removed JUnit 3 and 4 constructs with equivalent Jupiter lifecycle and assertion patterns
  • Run the full suite in your continuous integration pipeline after each change set

How we hand over

  • Deliver a written mapping of old test patterns to their JUnit 5 equivalents for your team to reuse
  • Document the test setup conventions, deployment annotations and extension registration in your repository
  • Provide a record of which tests were rewritten, merged or removed, with the reason for each
  • Walk your engineers through the suite so they can add new process tests without the migration team
  • Hand over the pass results and open items needed for your Flowable 8 upgrade sign-off

How we support

  • Support the test migration through a fixed-scope engagement with agreed deliverables and timelines
  • Offer a retainer for ongoing support if your team wants help with the Flowable 8 upgrade itself
  • Review new test failures that appear while your application and engine versions move together
  • Ask us to confirm any test behavior you need validated against your own environment and data

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.