Skip to content

Commit 7ef4278

Browse files
Add E2E tests for the spring sample (#4640)
Add E2E tests for the spring sample, and change the Java version of the sentry-system-test-support package. --------- Co-authored-by: Alexander Dinauer <[email protected]>
1 parent c8125f3 commit 7ef4278

File tree

10 files changed

+177
-52
lines changed

10 files changed

+177
-52
lines changed

.github/workflows/system-tests-backend.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ jobs:
8181
- sample: "sentry-samples-spring-jakarta"
8282
agent: "false"
8383
agent-auto-init: "true"
84+
- sample: "sentry-samples-spring"
85+
agent: "false"
86+
agent-auto-init: "true"
8487
steps:
8588
- uses: actions/checkout@v5
8689
with:

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ feign-gson = { module = "io.github.openfeign:feign-gson", version.ref = "feign"
9797
graphql-java17 = { module = "com.graphql-java:graphql-java", version = "17.3" }
9898
graphql-java22 = { module = "com.graphql-java:graphql-java", version = "22.1" }
9999
graphql-java24 = { module = "com.graphql-java:graphql-java", version = "24.0" }
100+
jackson-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson" }
100101
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
101102
jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
102103
jetbrains-annotations = { module = "org.jetbrains:annotations", version = "23.0.0" }
@@ -176,6 +177,8 @@ springboot4-starter-actuator = { module = "org.springframework.boot:spring-boot-
176177
timber = { module = "com.jakewharton.timber:timber", version = "4.7.1" }
177178

178179
# tomcat libraries
180+
tomcat-catalina = { module = "org.apache.tomcat:tomcat-catalina", version = "9.0.108" }
181+
tomcat-embed-jasper = { module = "org.apache.tomcat.embed:tomcat-embed-jasper", version = "9.0.108" }
179182
tomcat-catalina-jakarta = { module = "org.apache.tomcat:tomcat-catalina", version = "11.0.10" }
180183
tomcat-embed-jasper-jakarta = { module = "org.apache.tomcat.embed:tomcat-embed-jasper", version = "11.0.10" }
181184

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,90 @@
1-
import org.jetbrains.kotlin.config.KotlinCompilerVersion
21
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
32
import org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
43

54
plugins {
6-
alias(libs.plugins.springboot2) apply false
7-
alias(libs.plugins.spring.dependency.management)
8-
alias(libs.plugins.kotlin.jvm)
9-
alias(libs.plugins.kotlin.spring)
10-
id("war")
11-
alias(libs.plugins.gretty)
5+
application
6+
alias(libs.plugins.springboot2) apply false
7+
alias(libs.plugins.spring.dependency.management)
8+
alias(libs.plugins.kotlin.jvm)
9+
alias(libs.plugins.kotlin.spring)
10+
id("war")
11+
alias(libs.plugins.gretty)
1212
}
1313

14+
application { mainClass.set("io.sentry.samples.spring.Main") }
15+
16+
// Ensure WAR is up to date before run task
17+
tasks.named("run") { dependsOn(tasks.named("war")) }
18+
1419
group = "io.sentry.sample.spring"
20+
1521
version = "0.0.1-SNAPSHOT"
1622

1723
java {
18-
sourceCompatibility = JavaVersion.VERSION_1_8
19-
targetCompatibility = JavaVersion.VERSION_1_8
24+
sourceCompatibility = JavaVersion.VERSION_1_8
25+
targetCompatibility = JavaVersion.VERSION_1_8
2026
}
2127

22-
spotless {
23-
kotlinGradle {
24-
// This file throws an unclear error
25-
targetExclude("build.gradle.kts")
26-
}
27-
}
28-
29-
repositories {
30-
mavenCentral()
31-
}
28+
repositories { mavenCentral() }
3229

3330
dependencyManagement {
34-
imports {
35-
mavenBom(BOM_COORDINATES)
36-
}
31+
imports {
32+
mavenBom(BOM_COORDINATES)
33+
mavenBom(libs.kotlin.bom.get().toString())
34+
mavenBom(libs.jackson.bom.get().toString())
35+
}
3736
}
3837

3938
dependencies {
40-
implementation(Config.Libs.springWeb)
41-
implementation(Config.Libs.springAop)
42-
implementation(Config.Libs.aspectj)
43-
implementation(Config.Libs.springSecurityWeb)
44-
implementation(Config.Libs.springSecurityConfig)
45-
implementation(Config.Libs.kotlinReflect)
46-
implementation(kotlin(Config.kotlinStdLib, KotlinCompilerVersion.VERSION))
47-
implementation(projects.sentrySpring)
48-
implementation(projects.sentryLogback)
49-
implementation(libs.logback.classic)
50-
implementation(libs.servlet.api)
51-
testImplementation(libs.springboot.starter.test) {
52-
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
53-
}
54-
}
39+
implementation(Config.Libs.springWeb)
40+
implementation(Config.Libs.springAop)
41+
implementation(Config.Libs.aspectj)
42+
implementation(Config.Libs.springSecurityWeb)
43+
implementation(Config.Libs.springSecurityConfig)
44+
implementation(Config.Libs.kotlinReflect)
45+
implementation(kotlin(Config.kotlinStdLib))
46+
implementation(projects.sentrySpring)
47+
implementation(projects.sentryLogback)
48+
implementation(libs.jackson.databind)
49+
implementation(libs.logback.classic)
50+
implementation(libs.servlet.api)
5551

56-
tasks.withType<Test>().configureEach {
57-
useJUnitPlatform()
52+
implementation(libs.tomcat.catalina)
53+
implementation(libs.tomcat.embed.jasper)
54+
55+
testImplementation(projects.sentrySystemTestSupport)
56+
testImplementation(libs.kotlin.test.junit)
57+
testImplementation(libs.springboot.starter.test) {
58+
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
59+
}
5860
}
5961

6062
tasks.withType<KotlinCompile>().configureEach {
61-
kotlin {
62-
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
63-
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
64-
}
63+
kotlin {
64+
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
65+
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
66+
}
67+
}
68+
69+
configure<SourceSetContainer> { test { java.srcDir("src/test/java") } }
70+
71+
tasks.register<Test>("systemTest").configure {
72+
group = "verification"
73+
description = "Runs the System tests"
74+
75+
outputs.upToDateWhen { false }
76+
77+
maxParallelForks = 1
78+
79+
// Cap JVM args per test
80+
minHeapSize = "128m"
81+
maxHeapSize = "1g"
82+
83+
filter { includeTestsMatching("io.sentry.systemtest*") }
84+
}
85+
86+
tasks.named("test").configure {
87+
require(this is Test)
88+
89+
filter { excludeTestsMatching("io.sentry.systemtest.*") }
6590
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.sentry.samples.spring;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import org.apache.catalina.LifecycleException;
6+
import org.apache.catalina.startup.Tomcat;
7+
8+
public class Main {
9+
10+
public static void main(String[] args) throws LifecycleException, IOException {
11+
File webappsDirectory = new File("./tomcat.8080/webapps");
12+
if (!webappsDirectory.exists()) {
13+
boolean didCreateDirectories = webappsDirectory.mkdirs();
14+
if (!didCreateDirectories) {
15+
throw new RuntimeException(
16+
"Failed to create directory required by Tomcat: " + webappsDirectory.getAbsolutePath());
17+
}
18+
}
19+
20+
String pathToWar = "./build/libs";
21+
String warName = "sentry-samples-spring-0.0.1-SNAPSHOT";
22+
File war = new File(pathToWar + "/" + warName + ".war");
23+
24+
Tomcat tomcat = new Tomcat();
25+
tomcat.setPort(8080);
26+
tomcat.getConnector();
27+
28+
tomcat.addWebapp("/" + warName, war.getCanonicalPath());
29+
tomcat.start();
30+
tomcat.getServer().await();
31+
}
32+
}

sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/Person.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package io.sentry.samples.spring.web;
22

3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
36
public class Person {
47
private final String firstName;
58
private final String lastName;
69

7-
public Person(String firstName, String lastName) {
10+
@JsonCreator
11+
public Person(
12+
@JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName) {
813
this.firstName = firstName;
914
this.lastName = lastName;
1015
}

sentry-samples/sentry-samples-spring/src/main/java/io/sentry/samples/spring/web/PersonController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public PersonController(PersonService personService) {
2222
}
2323

2424
@GetMapping("{id}")
25-
Person person(@PathVariable Long id) {
25+
Person person(@PathVariable("id") Long id) {
2626
Sentry.logger().warn("warn Sentry logging");
2727
Sentry.logger().error("error Sentry logging");
2828
Sentry.logger().info("hello %s %s", "there", "world!");
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.sentry
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertTrue
5+
6+
class DummyTest {
7+
@Test
8+
fun `the only test`() {
9+
// only needed to have more than 0 tests and not fail the build
10+
assertTrue(true)
11+
}
12+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.sentry.systemtest
2+
3+
import io.sentry.systemtest.util.TestHelper
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
import org.junit.Before
7+
8+
class PersonSystemTest {
9+
lateinit var testHelper: TestHelper
10+
11+
@Before
12+
fun setup() {
13+
testHelper = TestHelper("http://localhost:8080/sentry-samples-spring-0.0.1-SNAPSHOT")
14+
testHelper.reset()
15+
}
16+
17+
@Test
18+
fun `get person fails`() {
19+
val restClient = testHelper.restClient
20+
restClient.getPerson(11L)
21+
assertEquals(500, restClient.lastKnownStatusCode)
22+
23+
testHelper.ensureTransactionReceived { transaction, envelopeHeader ->
24+
testHelper.doesTransactionHaveOp(transaction, "http.server")
25+
}
26+
27+
Thread.sleep(10000)
28+
29+
testHelper.ensureLogsReceived { logs, envelopeHeader ->
30+
testHelper.doesContainLogWithBody(logs, "warn Sentry logging") &&
31+
testHelper.doesContainLogWithBody(logs, "error Sentry logging") &&
32+
testHelper.doesContainLogWithBody(logs, "hello there world!")
33+
}
34+
}
35+
36+
@Test
37+
fun `create person works`() {
38+
val restClient = testHelper.restClient
39+
val person = Person("firstA", "lastB")
40+
val returnedPerson = restClient.createPerson(person)
41+
assertEquals(200, restClient.lastKnownStatusCode)
42+
43+
assertEquals(person.firstName, returnedPerson!!.firstName)
44+
assertEquals(person.lastName, returnedPerson!!.lastName)
45+
}
46+
}

sentry-system-test-support/build.gradle.kts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ plugins {
99
}
1010

1111
configure<JavaPluginExtension> {
12-
sourceCompatibility = JavaVersion.VERSION_17
13-
targetCompatibility = JavaVersion.VERSION_17
12+
sourceCompatibility = JavaVersion.VERSION_1_8
13+
targetCompatibility = JavaVersion.VERSION_1_8
1414
}
1515

1616
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
17-
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
17+
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
1818
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
1919
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
2020
}
@@ -26,10 +26,8 @@ dependencies {
2626

2727
compileOnly(libs.jetbrains.annotations)
2828
compileOnly(libs.nopen.annotations)
29-
compileOnly(libs.springboot3.starter.test) {
30-
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
31-
}
32-
compileOnly(libs.springboot3.starter.web)
29+
30+
compileOnly(libs.springboot.starter.web)
3331

3432
implementation(libs.jackson.databind)
3533
implementation(libs.jackson.kotlin)

test/system-test-runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ def run_manual_test_mode(self, sample_module: str, java_agent: str,
712712
def get_available_modules(self) -> List[ModuleConfig]:
713713
"""Get list of all available test modules."""
714714
return [
715+
ModuleConfig("sentry-samples-spring", "false", "true", "false"),
715716
ModuleConfig("sentry-samples-spring-jakarta", "false", "true", "false"),
716717
ModuleConfig("sentry-samples-spring-boot", "false", "true", "false"),
717718
ModuleConfig("sentry-samples-spring-boot-opentelemetry-noagent", "false", "true", "false"),

0 commit comments

Comments
 (0)