From 89facff39b1a16f12921bd26d6d119b19303dab3 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 24 Oct 2025 14:20:17 +0200 Subject: [PATCH 1/4] Bump Spring Boot 4 to RC1 --- gradle/libs.versions.toml | 3 ++- sentry-spring-7/build.gradle.kts | 1 + .../graphql/SentrySpringSubscriptionHandlerTest.kt | 8 ++++---- .../sentry/spring7/mvc/SentrySpringIntegrationTest.kt | 10 ++++++---- .../spring7/webflux/SentryWebfluxIntegrationTest.kt | 8 ++++---- sentry-spring-boot-4/build.gradle.kts | 1 + .../spring/boot4/it/SentrySpringIntegrationTest.kt | 4 ++-- 7 files changed, 20 insertions(+), 15 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6672de2d6e7..c423ac8cb3c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ retrofit = "2.9.0" slf4j = "1.7.30" springboot2 = "2.7.18" springboot3 = "3.5.0" -springboot4 = "4.0.0-M3" +springboot4 = "4.0.0-RC1" # Android targetSdk = "34" compileSdk = "34" @@ -165,6 +165,7 @@ springboot3-starter-security = { module = "org.springframework.boot:spring-boot- springboot3-starter-jdbc = { module = "org.springframework.boot:spring-boot-starter-jdbc", version.ref = "springboot3" } springboot3-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "springboot3" } springboot4-otel = { module = "io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter", version.ref = "otelInstrumentation" } +springboot4-resttestclient = { module = "org.springframework.boot:spring-boot-resttestclient", version.ref = "springboot4" } springboot4-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springboot4" } springboot4-starter-graphql = { module = "org.springframework.boot:spring-boot-starter-graphql", version.ref = "springboot4" } springboot4-starter-quartz = { module = "org.springframework.boot:spring-boot-starter-quartz", version.ref = "springboot4" } diff --git a/sentry-spring-7/build.gradle.kts b/sentry-spring-7/build.gradle.kts index a8071860ad0..8102909afb0 100644 --- a/sentry-spring-7/build.gradle.kts +++ b/sentry-spring-7/build.gradle.kts @@ -75,6 +75,7 @@ dependencies { testImplementation(libs.springboot4.starter.webflux) testImplementation(libs.springboot4.starter.restclient) testImplementation(libs.springboot4.starter.webclient) + testImplementation(libs.springboot4.resttestclient) testImplementation(projects.sentryReactor) } diff --git a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/graphql/SentrySpringSubscriptionHandlerTest.kt b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/graphql/SentrySpringSubscriptionHandlerTest.kt index c216b4595d2..1ed217037a2 100644 --- a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/graphql/SentrySpringSubscriptionHandlerTest.kt +++ b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/graphql/SentrySpringSubscriptionHandlerTest.kt @@ -40,8 +40,8 @@ class SentrySpringSubscriptionHandlerTest { whenever(parameters.environment).thenReturn(dataFetchingEnvironment) val resultObject = SentrySpringSubscriptionHandler() - .onSubscriptionResult(Flux.error(exception), scopes, exceptionReporter, parameters) - assertThrows { (resultObject as Flux).blockFirst() } + .onSubscriptionResult(Flux.error(exception), scopes, exceptionReporter, parameters) + assertThrows { (resultObject as Flux).blockFirst() } verify(exceptionReporter) .captureThrowable( @@ -77,12 +77,12 @@ class SentrySpringSubscriptionHandlerTest { val resultObject = SentrySpringSubscriptionHandler() .onSubscriptionResult( - Flux.error(wrappedException), + Flux.error(wrappedException), scopes, exceptionReporter, parameters, ) - assertThrows { (resultObject as Flux).blockFirst() } + assertThrows { (resultObject as Flux).blockFirst() } verify(exceptionReporter) .captureThrowable( diff --git a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt index 1127456cc6c..a6324bfa9fe 100644 --- a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt @@ -42,9 +42,9 @@ import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.resttestclient.TestRestTemplate import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.web.server.test.LocalServerPort -import org.springframework.boot.web.server.test.client.TestRestTemplate +import org.springframework.boot.test.web.server.LocalServerPort import org.springframework.boot.web.servlet.FilterRegistrationBean import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -80,13 +80,15 @@ import org.springframework.web.reactive.function.client.WebClient class SentrySpringIntegrationTest { companion object { + @JvmStatic @BeforeClass - fun `configure awaitlity`() { + fun `configure awaitlity`(): Unit { Awaitility.setDefaultTimeout(500, TimeUnit.MILLISECONDS) } + @JvmStatic @AfterClass - fun `reset awaitility`() { + fun `reset awaitility`(): Unit { Awaitility.reset() } } diff --git a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/webflux/SentryWebfluxIntegrationTest.kt b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/webflux/SentryWebfluxIntegrationTest.kt index 2d44b40c27d..a91023b4ba0 100644 --- a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/webflux/SentryWebfluxIntegrationTest.kt +++ b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/webflux/SentryWebfluxIntegrationTest.kt @@ -27,10 +27,10 @@ import org.mockito.kotlin.whenever import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.ApplicationRunner import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.security.autoconfigure.reactive.ReactiveSecurityAutoConfiguration -import org.springframework.boot.security.autoconfigure.servlet.SecurityAutoConfiguration +import org.springframework.boot.security.autoconfigure.SecurityAutoConfiguration +import org.springframework.boot.security.autoconfigure.web.reactive.ReactiveWebSecurityAutoConfiguration import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.web.server.test.LocalServerPort +import org.springframework.boot.test.web.server.LocalServerPort import org.springframework.context.annotation.Bean import org.springframework.http.ResponseEntity import org.springframework.test.context.junit4.SpringRunner @@ -136,7 +136,7 @@ class SentryWebfluxIntegrationTest { } @SpringBootApplication( - exclude = [ReactiveSecurityAutoConfiguration::class, SecurityAutoConfiguration::class] + exclude = [ReactiveWebSecurityAutoConfiguration::class, SecurityAutoConfiguration::class] ) open class App { private val transport = mock().also { whenever(it.isHealthy).thenReturn(true) } diff --git a/sentry-spring-boot-4/build.gradle.kts b/sentry-spring-boot-4/build.gradle.kts index 897d59c3c20..96f2f39adab 100644 --- a/sentry-spring-boot-4/build.gradle.kts +++ b/sentry-spring-boot-4/build.gradle.kts @@ -102,6 +102,7 @@ dependencies { testImplementation(libs.springboot4.starter.webflux) testImplementation(libs.springboot4.starter.restclient) testImplementation(libs.springboot4.starter.webclient) + testImplementation(libs.springboot4.resttestclient) } configure { test { java.srcDir("src/test/java") } } diff --git a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/it/SentrySpringIntegrationTest.kt b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/it/SentrySpringIntegrationTest.kt index 998dfaaf867..473b60def12 100644 --- a/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/it/SentrySpringIntegrationTest.kt +++ b/sentry-spring-boot-4/src/test/kotlin/io/sentry/spring/boot4/it/SentrySpringIntegrationTest.kt @@ -24,9 +24,9 @@ import org.mockito.kotlin.whenever import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.resttestclient.TestRestTemplate import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.web.server.test.LocalServerPort -import org.springframework.boot.web.server.test.client.TestRestTemplate +import org.springframework.boot.test.web.server.LocalServerPort import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.HttpEntity From 5b0a733c9949764f8783e6a4865385ced55ed844 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 24 Oct 2025 15:16:23 +0200 Subject: [PATCH 2/4] fix tests --- .../io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt | 7 ++----- .../spring/jakarta/mvc/SentrySpringIntegrationTest.kt | 7 ++----- .../io/sentry/spring/mvc/SentrySpringIntegrationTest.kt | 7 ++----- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt index a6324bfa9fe..169ef346865 100644 --- a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt @@ -22,7 +22,6 @@ import io.sentry.spring7.tracing.SentryTracingConfiguration import io.sentry.spring7.tracing.SentryTracingFilter import io.sentry.spring7.tracing.SentryTransaction import io.sentry.transport.ITransport -import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -232,10 +231,8 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - await.during(Duration.ofSeconds(2)).untilAsserted { - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) - } + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) } @Test diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt index 6e2ea53fdfd..9630460cd98 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt @@ -22,7 +22,6 @@ import io.sentry.spring.jakarta.tracing.SentryTracingConfiguration import io.sentry.spring.jakarta.tracing.SentryTracingFilter import io.sentry.spring.jakarta.tracing.SentryTransaction import io.sentry.transport.ITransport -import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -230,10 +229,8 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - await.during(Duration.ofSeconds(2)).untilAsserted { - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) - } + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) } @Test diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt index d6c5fd2aa79..63d29dd78db 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt @@ -22,7 +22,6 @@ import io.sentry.spring.tracing.SentryTracingConfiguration import io.sentry.spring.tracing.SentryTracingFilter import io.sentry.spring.tracing.SentryTransaction import io.sentry.transport.ITransport -import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -231,10 +230,8 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - await.during(Duration.ofSeconds(2)).untilAsserted { - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) - } + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) } @Test From 7a7668021fcc87ae90f9fbf8393527b50763395a Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Wed, 5 Nov 2025 15:07:53 +0100 Subject: [PATCH 3/4] fix test assertions --- .../mvc/SentrySpringIntegrationTest.kt | 189 ++++++++++-------- 1 file changed, 107 insertions(+), 82 deletions(-) diff --git a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt index 169ef346865..4b7e806730f 100644 --- a/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-7/src/test/kotlin/io/sentry/spring7/mvc/SentrySpringIntegrationTest.kt @@ -22,6 +22,7 @@ import io.sentry.spring7.tracing.SentryTracingConfiguration import io.sentry.spring7.tracing.SentryTracingFilter import io.sentry.spring7.tracing.SentryTransaction import io.sentry.transport.ITransport +import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -116,17 +117,19 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") - assertThat(event.user).isNotNull() - assertThat(event.user!!.username).isEqualTo("user") - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") + assertThat(event.user).isNotNull() + assertThat(event.user!!.username).isEqualTo("user") + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -141,14 +144,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -163,14 +168,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -182,14 +189,16 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.user).isNotNull() - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.user).isNotNull() + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -198,18 +207,20 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.exceptions).isNotNull().isNotEmpty - val ex = event.exceptions!!.first() - assertThat(ex.value).isEqualTo("something went wrong") - assertThat(ex.mechanism).isNotNull() - assertThat(ex.mechanism!!.isHandled).isFalse() - assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.exceptions).isNotNull().isNotEmpty + val ex = event.exceptions!!.first() + assertThat(ex.value).isEqualTo("something went wrong") + assertThat(ex.mechanism).isNotNull() + assertThat(ex.mechanism!!.isHandled).isFalse() + assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) + }, + anyOrNull(), + ) + } } @Test @@ -218,11 +229,13 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, + anyOrNull(), + ) + } } @Test @@ -231,37 +244,45 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + await.atMost(3, TimeUnit.SECONDS).during(Duration.ofSeconds(2)).untilAsserted { + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnException(exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception in later param`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnExceptionAsLaterParam("a", "b", exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryTransaction creates transaction`() { someService.aMethod() - verify(transport) - .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + await.untilAsserted { + verify(transport) + .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + } } @Test @@ -271,14 +292,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("bean") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("bean") + }, + anyOrNull(), + ) + } } @Test @@ -288,14 +311,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") + }, + anyOrNull(), + ) + } } @Test From 8542a60d7c6c3925c5a5030e16a90174feaddc71 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Wed, 5 Nov 2025 15:38:37 +0100 Subject: [PATCH 4/4] fix more test assertions --- .../mvc/SentrySpringIntegrationTest.kt | 189 ++++++++++-------- .../spring/mvc/SentrySpringIntegrationTest.kt | 189 ++++++++++-------- 2 files changed, 214 insertions(+), 164 deletions(-) diff --git a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt index 9630460cd98..6d399323f5f 100644 --- a/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/mvc/SentrySpringIntegrationTest.kt @@ -22,6 +22,7 @@ import io.sentry.spring.jakarta.tracing.SentryTracingConfiguration import io.sentry.spring.jakarta.tracing.SentryTracingFilter import io.sentry.spring.jakarta.tracing.SentryTransaction import io.sentry.transport.ITransport +import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -114,17 +115,19 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") - assertThat(event.user).isNotNull() - assertThat(event.user!!.username).isEqualTo("user") - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") + assertThat(event.user).isNotNull() + assertThat(event.user!!.username).isEqualTo("user") + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -139,14 +142,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -161,14 +166,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -180,14 +187,16 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.user).isNotNull() - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.user).isNotNull() + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -196,18 +205,20 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.exceptions).isNotNull().isNotEmpty - val ex = event.exceptions!!.first() - assertThat(ex.value).isEqualTo("something went wrong") - assertThat(ex.mechanism).isNotNull() - assertThat(ex.mechanism!!.isHandled).isFalse() - assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.exceptions).isNotNull().isNotEmpty + val ex = event.exceptions!!.first() + assertThat(ex.value).isEqualTo("something went wrong") + assertThat(ex.mechanism).isNotNull() + assertThat(ex.mechanism!!.isHandled).isFalse() + assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) + }, + anyOrNull(), + ) + } } @Test @@ -216,11 +227,13 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, + anyOrNull(), + ) + } } @Test @@ -229,37 +242,45 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + await.atMost(3, TimeUnit.SECONDS).during(Duration.ofSeconds(2)).untilAsserted { + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnException(exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception in later param`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnExceptionAsLaterParam("a", "b", exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryTransaction creates transaction`() { someService.aMethod() - verify(transport) - .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + await.untilAsserted { + verify(transport) + .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + } } @Test @@ -269,14 +290,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("bean") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("bean") + }, + anyOrNull(), + ) + } } @Test @@ -286,14 +309,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") + }, + anyOrNull(), + ) + } } @Test diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt index 63d29dd78db..26afd5811bf 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/mvc/SentrySpringIntegrationTest.kt @@ -22,6 +22,7 @@ import io.sentry.spring.tracing.SentryTracingConfiguration import io.sentry.spring.tracing.SentryTracingFilter import io.sentry.spring.tracing.SentryTransaction import io.sentry.transport.ITransport +import java.time.Duration import java.util.concurrent.Callable import java.util.concurrent.TimeUnit import kotlin.test.BeforeTest @@ -115,17 +116,19 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") - assertThat(event.user).isNotNull() - assertThat(event.user!!.username).isEqualTo("user") - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.url).isEqualTo("http://localhost:$port/hello") + assertThat(event.user).isNotNull() + assertThat(event.user!!.username).isEqualTo("user") + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -140,14 +143,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -162,14 +167,16 @@ class SentrySpringIntegrationTest { Void::class.java, ) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.request).isNotNull() - assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.request).isNotNull() + assertThat(event.request!!.data).isEqualTo("""{"body":"content"}""") + }, + anyOrNull(), + ) + } } @Test @@ -181,14 +188,16 @@ class SentrySpringIntegrationTest { restTemplate.exchange("http://localhost:$port/hello", HttpMethod.GET, entity, Void::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.user).isNotNull() - assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.user).isNotNull() + assertThat(event.user!!.ipAddress).isEqualTo("169.128.0.1") + }, + anyOrNull(), + ) + } } @Test @@ -197,18 +206,20 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> - assertThat(event.exceptions).isNotNull().isNotEmpty - val ex = event.exceptions!!.first() - assertThat(ex.value).isEqualTo("something went wrong") - assertThat(ex.mechanism).isNotNull() - assertThat(ex.mechanism!!.isHandled).isFalse() - assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> + assertThat(event.exceptions).isNotNull().isNotEmpty + val ex = event.exceptions!!.first() + assertThat(ex.value).isEqualTo("something went wrong") + assertThat(ex.mechanism).isNotNull() + assertThat(ex.mechanism!!.isHandled).isFalse() + assertThat(ex.mechanism!!.type).isEqualTo(SentryExceptionResolver.MECHANISM_TYPE) + }, + anyOrNull(), + ) + } } @Test @@ -217,11 +228,13 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws", String::class.java) - verify(transport) - .send( - checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { event -> assertThat(event.transaction).isEqualTo("GET /throws") }, + anyOrNull(), + ) + } } @Test @@ -230,37 +243,45 @@ class SentrySpringIntegrationTest { restTemplate.getForEntity("http://localhost:$port/throws-handled", String::class.java) - verify(transport, never()) - .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + await.atMost(3, TimeUnit.SECONDS).during(Duration.ofSeconds(2)).untilAsserted { + verify(transport, never()) + .send(checkEvent { event -> assertThat(event).isNotNull() }, anyOrNull()) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnException(exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryCaptureException captures exception in later param`() { val exception = java.lang.RuntimeException("test exception") anotherService.aMethodThatTakesAnExceptionAsLaterParam("a", "b", exception) - verify(transport) - .send( - checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { assertThat(it.exceptions!!.first().value).isEqualTo(exception.message) }, + anyOrNull(), + ) + } } @Test fun `calling a method annotated with @SentryTransaction creates transaction`() { someService.aMethod() - verify(transport) - .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + await.untilAsserted { + verify(transport) + .send(checkTransaction { assertThat(it.status).isEqualTo(SpanStatus.OK) }, anyOrNull()) + } } @Test @@ -270,14 +291,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("bean") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("bean") + }, + anyOrNull(), + ) + } } @Test @@ -287,14 +310,16 @@ class SentrySpringIntegrationTest { } catch (e: Exception) { scopes.captureException(e) } - verify(transport) - .send( - checkEvent { - assertThat(it.contexts.trace).isNotNull - assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") - }, - anyOrNull(), - ) + await.untilAsserted { + verify(transport) + .send( + checkEvent { + assertThat(it.contexts.trace).isNotNull + assertThat(it.contexts.trace!!.operation).isEqualTo("child-op") + }, + anyOrNull(), + ) + } } @Test