skip to content

A Maven project holds three Gatling simulation classes, and mvn gatling:test fails on the CI runner because more than one simulation is available - how do you make the job run the one you want?

level: middleimportance: must knowfreq 58%

answer

  1. The plugin refuses to guess, not fails randomly
  2. Interactive by default, headless under CI
  3. Force the fully qualified class name
  4. -Dgatling.simulationClass or the simulationClass element

basics

~10 s

Force the class. Pass -Dgatling.simulationClass=com.project.simu.CheckoutSimulation on the mvn command line, or set a simulationClass element in the plugin configuration. Under CI the goal deliberately refuses to guess when several simulations exist.

solid answer

~40 s

`mvn gatling:test` runs interactively and offers the simulation classes it found. It skips that prompt in five situations: only one simulation exists; the class is forced with `-Dgatling.simulationClass=<FullyQualifiedClassName>`; non-interactive mode is forced; Maven is in batch mode (`-B`); or the `CI` environment variable is set to `true`. In the last three, with more than one simulation available the goal **fails** rather than choosing — deliberately, so a pipeline never silently runs the wrong load test. The fix is therefore to name the class: the system property per job, or a `<simulationClass>` element in the plugin's `<configuration>` if the project only ever runs one.

code

bash · 5 lines
bash
# Fails on CI: three simulations, nobody to answer the prompt
CI=true mvn gatling:test

# Name the class and the job is deterministic
mvn gatling:test -Dgatling.simulationClass=com.project.simu.CheckoutSimulation

go deeper

for a junior

Recall that the fix is to name the simulation class, and that -Dgatling.simulationClass takes the fully qualified name rather than the short one.

for a middle

Explain the five conditions that turn the prompt off, and that three of them fail rather than choose when several simulations are available.

for a senior

Argue why failing loudly beats guessing, and decide whether the class name belongs in the build file or in the pipeline invocation.

for a principal

Set the convention for the estate so every repository answers 'which simulation does this job run' the same way, in one reviewable place.

A Gatling project with one simulation class is easy: every launcher finds it and runs it. The moment a second class lands, the build tool has to decide **which** one you meant, and the plugins deliberately refuse to guess when nobody is there to ask. ## What `gatling:test` actually does `mvn gatling:test` runs in **interactive mode** and suggests the simulation class to launch. It skips the prompt in exactly five situations: 1. there is only one simulation available; 2. the class is forced with `-Dgatling.simulationClass=<FullyQualifiedClassName>`; 3. non-interactive mode is forced; 4. Maven is in batch mode (the `-B` option); 5. the `CI` environment variable is set to `true`. Cases 3, 4 and 5 disable the prompt but do **not** substitute a choice: with more than one simulation available, the goal **fails**. That is the message a CI runner produces, and it is a feature — a pipeline that guessed could run the wrong load test for months without anyone noticing. ## Fixing the three-simulation project Say the project holds `com.project.simu.CheckoutSimulation`, `com.project.simu.SearchSimulation` and `com.project.simu.LoginSimulation`, and the nightly job must run the checkout one. Two places can carry that decision: | Where | How | When it fits | |---|---|---| | The pipeline | `mvn gatling:test -Dgatling.simulationClass=com.project.simu.CheckoutSimulation` | one build serves several jobs, each pinning a different class | | The build file | `<configuration><simulationClass>com.project.simu.CheckoutSimulation</simulationClass></configuration>` | the repository always means one simulation, and the choice should be reviewable in a diff | Pick one. Carrying the same answer in both places is how a job quietly drifts away from what the build file claims. ### A third option: bind an execution per simulation If the project genuinely must run more than one simulation from a single Maven invocation, the plugin's goals can be bound to lifecycle phases through `<executions>`, and each `<execution>` can carry its own `<configuration>`. Three executions, three `<simulationClass>` values, one `mvn verify` — the goal still selects one simulation per execution, but the list of what runs is now written down in the POM where a reviewer can see it. By default an `<execution>` of `test` binds to `integration-test` and one of `enterprisePackage` to `package`. ## The same problem in the other launchers - **Gradle.** `gatlingRun` prompts under the same rules, but the switches are task options rather than system properties: `--simulation=<FullyQualifiedClassName>` forces the class, `--non-interactive` forces headless mode, and the `CI` environment variable set to true does the same. Gradle additionally has `--all`, which runs every discovered simulation sequentially in alphabetic order. - **sbt.** `sbt 'Gatling/testOnly com.project.simu.CheckoutSimulation'` names the class directly; `Gatling/testFull` runs them all. - **JavaScript/TypeScript.** `npx gatling run` asks you to choose when several simulations are found, and `--simulation "my-simulation"` bypasses the prompt. Note the argument is the simulation's **name**, matching `src/my-simulation.gatling.js` or `.gatling.ts` — not a fully qualified class name. ## Why the core cannot help you here None of this discovery lives in Gatling itself. `io.gatling.app.Gatling` parses a small option set in which `--simulation` (short `-s`) names the class, and its selection code throws `IllegalArgumentException("Missing simulation class")` when nothing was supplied. Scanning the compiled output, presenting a menu and failing loudly under CI are all plugin behaviour layered on top. That is worth knowing because it tells you where to look when the behaviour surprises you: the build-tool plugin's version, not Gatling's. Under Gatling Enterprise the selection problem repeats one level up, with different vocabulary. `mvn gatling:enterpriseStart` prompts you to choose from the **deployed simulations**, and `-Dgatling.enterprise.simulationName="<simulation name>"` bypasses the prompt. The same `CI` environment variable disables interaction there, so a pipeline hits the identical shape of problem: say which one, or be asked. ## What counts as a simulation class Discovery is not a filename convention. Gatling's own class check rejects interfaces and abstract classes, and accepts a concrete class that extends a Gatling `Simulation`. The Gradle plugin used to detect simulations by file name ending in `Simulation` and stopped doing so in version 3.11.0, detecting classes that actually extend `Simulation` instead — which also means that in Kotlin and Scala, where the class name and the file name can differ, the **class** name is what matters. ## The practical checklist - If a CI job says more than one simulation is available, do not add `-B` or set `CI` — those are what produced the failure. Name the class. - Use the fully qualified class name; a simple name is not what the option takes. - If the goal reports that the named class is not a `Simulation`, check that it is concrete and extends Gatling's `Simulation`, and that it is on the classpath the plugin runs with. - If you genuinely want all three to run, that is `--all` on Gradle or `Gatling/testFull` on sbt. On Maven it means three invocations or three bound executions, because `gatling:test` selects one simulation per invocation.

  • What counts as a simulation class for the plugins' discovery?
    A concrete class that extends a Gatling `Simulation`. Interfaces and abstract classes are rejected. Since gatling-gradle-plugin 3.11.0 detection is based on the class extending `Simulation` rather than on a file name ending in `Simulation`, which matters in Kotlin and Scala where the two can differ.
  • How does the same problem look under Gradle and the JavaScript CLI?
    Gradle's `gatlingRun` prompts under the same rules and takes `--simulation=<FullyQualifiedClassName>`, `--non-interactive`, or the `CI` variable; it also has `--all`. The JavaScript CLI asks you to choose when several are found and takes `--simulation "my-simulation"`, which matches a file name rather than a class name.
  • Would setting the CI variable to false on the runner be a reasonable workaround?
    No. It would restore the interactive prompt on a machine with no one to answer it, so the job would hang or take whatever the plugin reads from a dead input stream. The failure is telling you the job has not said which simulation it means; answer that instead.

saying these in an interview costs you the question

  • Thinking the CI variable makes the goal pick a simulation for you
  • Expecting an alphabetical or first-found fallback when several classes exist
  • Passing a simple class name where a fully qualified name is required
  • Assuming Maven accepts the Gradle plugin's --simulation option