Most Spring Boot projects treat src/test/java as an internal implementation detail: it exists to make CI green and never leaves the build machine. But there’s a useful pattern that turns a subset of your tests into a portable, deployable artifact — one you can run after a deployment, against a real running environment, without needing a full dev toolchain, source checkout, or Maven installed on the target.

Once an application is deployed, you typically want a fast, focused check that the important paths actually work end-to-end: can it log in, can it reach the database, does the health endpoint respond, does a critical business flow complete. These are exactly the kind of tests you already write with JUnit — the only twist is where and when they run.

Step 1 — Tag the tests you want to select

Use JUnit 5’s @Tag to mark tests that should be treated as smoke/integration tests against a live system, as opposed to your regular unit tests that run on every build.

java

package com.example.app.smoke;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
@Tag("smoke")
class HealthEndpointSmokeTest {
@Test
void healthEndpointReportsUp() {
RestAssured.baseURI = System.getenv().getOrDefault("BASE_URL", "http://localhost:8080");
given()
.when().get("/actuator/health")
.then()
.statusCode(200)
.body("status", equalTo("UP"));
}
}

java

@Tag("smoke")
class LoginFlowSmokeTest {
@Test
void userCanLogInAndFetchProfile() {
// hits the real, deployed instance via BASE_URL
// ...
}
}

The key idea: these tests don’t use @SpringBootTest or an embedded context — they talk to a real, already-running instance over HTTP, addressed via an environment variable like BASE_URL.

Step 2 — Exclude the tag from the normal build, and build a separate artifact

Two things need to happen in pom.xml:

  1. Your regular mvn test / mvn verify build should not run smoke tests (they need a live target and shouldn’t slow down or break the main build).
  2. A separate, executable jar should be produced that contains only the compiled smoke test classes plus everything needed to run them standalone.

Excluding the tag from the default run

xml

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>smoke</excludedGroups>
</configuration>
</plugin>

Building a standalone, runnable test jar

The cleanest way to get a runnable jar for JUnit 5 tests is to bundle your compiled test classes together with the JUnit Platform Console Launcher, which can select and execute tests by tag from the command line. maven-shade-plugin builds the fat jar; maven-jar-plugin (via testJar goal) is not enough on its own since it won’t include dependencies.

xml

<build>
<plugins>
<!-- 1. Exclude smoke tests from the regular build -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>smoke</excludedGroups>
</configuration>
</plugin>
<!-- 2. Build a fat jar containing test classes + console launcher -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>smoke-test-jar</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>smoke-tests</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.junit.platform.console.ConsoleLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console-standalone</artifactId>
<version>1.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

This produces myapp-1.4.2-smoke-tests.jar, runnable directly:

bash

java -jar myapp-1.4.2-smoke-tests.jar --select-package com.example.app.smoke --include-tag smoke

Hinterlasse einen Kommentar

I’m Iman

Mein Name ist Iman Dabbaghi. Ich arbeite als Senior Software Engineer in der Schweiz. Außerdem interessiere ich mich sehr für gewaltfreie Kommunikation, Bachata-Tanz und Musik sowie fürs die Persönlichkeitsentwicklung.

Ich habe einen Masterabschluss in Informatik von der Universität Freiburg in Deutschland, bin Spring/Java Certified Professional (OCP), Certified Professional for Software Architecture (CPSA-F) und ein lebenslanger Lernender 🎓.

EN:

My name is Iman Dabbaghi. I work as a Senior Software Engineer in Switzerland. I am also very interessted in nonviolent communication, Bachata dance and music and also for personal development.

I hold a masters degree in computer science from the university of Freiburg in Germany, am a Spring / Java Certified Professional (OCP), Certified Software Architecture (CPSA-F) and Life Long Learner🎓

Let’s connect