From 9a8dc17d8c2ca0276e5de67b06aa80acac657bee Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 8 Jan 2016 19:08:34 +0100 Subject: [PATCH] [#89] Initial approach to the integration tests - Fixed the tests - Updated surefire - Added integration tests (for the moment ignored) - Fixed wrong surefire setup --- .settings.xml | 7 ++ README.adoc | 3 +- pom.xml | 82 +++++++------ spring-cloud-sleuth-core/pom.xml | 1 - .../sleuth/instrument/TraceCallable.java | 10 +- .../sleuth/instrument/TraceRunnable.java | 2 +- .../instrument/hystrix/TraceCommand.java | 14 ++- .../sleuth/DefaultTraceManagerTests.java | 32 +++-- .../sleuth/instrument/TraceRunnableTest.java | 16 +-- .../TraceableExecutorServiceTests.java | 30 ++--- ...nPassingForHystrixViaAnnotationsITest.java | 12 +- .../instrument/hystrix/TraceCommandTest.java | 23 +++- .../web/RestTemplateTraceAspectITest.java | 31 ++--- .../instrument/web/client/FeignTraceTest.java | 14 +-- .../TraceRestTemplateInterceptorTests.java | 1 + spring-cloud-sleuth-samples/pom.xml | 35 ++++-- .../pom.xml | 19 +++ .../main/java/sample/SampleBackground.java | 5 +- .../src/main/resources/logback.xml | 9 ++ .../MessagingApplicationDockerTests.java | 114 ++++++++++++++++++ .../src/test/resources/docker-compose.yml | 5 + .../pom.xml | 111 +++++++++++++++++ .../java/tools/AbstractIntegrationTest.java | 50 ++++++++ .../java/tools/AssertingRestTemplate.java | 55 +++++++++ .../src/main/java/tools/DockerTests.java | 7 ++ .../tools/IntegrationTestSpanCollector.java | 40 ++++++ .../java/tools/RequestSendingRunnable.java | 60 +++++++++ .../stream/ZipkinMessageListenerTests.java | 8 +- .../zipkin/ZipkinSpanListenerTests.java | 3 +- 29 files changed, 661 insertions(+), 138 deletions(-) create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/resources/logback.xml create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationDockerTests.java create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/resources/docker-compose.yml create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/DockerTests.java create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/IntegrationTestSpanCollector.java create mode 100644 spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java diff --git a/.settings.xml b/.settings.xml index 6c355129e..32e8266cc 100644 --- a/.settings.xml +++ b/.settings.xml @@ -62,5 +62,12 @@ + + + ide + true + diff --git a/README.adoc b/README.adoc index e4a5fa9bc..c1b10d72d 100644 --- a/README.adoc +++ b/README.adoc @@ -69,10 +69,11 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master == Building :jdkversion: 1.7 +:testjdkversion: 1.8 === Basic Compile and Test -To build the source you will need to install JDK {jdkversion}. +To build the source you will need to install JDK {jdkversion}. However to run the tests you need {testjdkversion}. Spring Cloud uses Maven for most build-related activities, and you should be able to get off the ground quite quickly by cloning the diff --git a/pom.xml b/pom.xml index 0591e6dc4..d34a5c007 100644 --- a/pom.xml +++ b/pom.xml @@ -89,37 +89,6 @@ - - maven-surefire-plugin - 2.6 - - false - - **/*Spec.java - - - - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.7 - - - signature-check - verify - - check - - - - - - org.codehaus.mojo.signature - java17 - 1.0 - - - @@ -162,11 +131,6 @@ hamcrest-core test - - org.codehaus.groovy - groovy - test - com.jayway.awaitility awaitility @@ -185,6 +149,12 @@ 1.0.4 test + + org.assertj + assertj-core + 2.1.0 + test + @@ -194,6 +164,7 @@ 1.7 1.8 1.8 + 2.9 @@ -244,6 +215,45 @@ + + integration + + false + + + + + maven-surefire-plugin + ${surefire.plugin.version} + + false + tools.DockerTests + + + + + + + !integration + + false + + + + + maven-surefire-plugin + ${surefire.plugin.version} + + false + + **/Abstract*.java + **/*DockerTests.java + + + + + + ide diff --git a/spring-cloud-sleuth-core/pom.xml b/spring-cloud-sleuth-core/pom.xml index 13edadcbf..4d6c95003 100644 --- a/spring-cloud-sleuth-core/pom.xml +++ b/spring-cloud-sleuth-core/pom.xml @@ -95,7 +95,6 @@ org.assertj assertj-core - 2.1.0 test diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java index 902a2376f..f7431e8c5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceCallable.java @@ -16,20 +16,20 @@ package org.springframework.cloud.sleuth.instrument; -import java.util.concurrent.Callable; - +import lombok.EqualsAndHashCode; +import lombok.Value; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceManager; -import lombok.EqualsAndHashCode; -import lombok.Value; +import java.util.concurrent.Callable; /** * @author Spencer Gibb */ @Value @EqualsAndHashCode(callSuper = false) -public class TraceCallable extends TraceDelegate>implements Callable { +public class TraceCallable extends TraceDelegate> implements Callable { + public TraceCallable(TraceManager traceManager, Callable delegate) { super(traceManager, delegate); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java index 844f32ca3..d9eb0c49d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/TraceRunnable.java @@ -27,7 +27,7 @@ import lombok.Value; */ @Value @EqualsAndHashCode(callSuper = false) -public class TraceRunnable extends TraceDelegateimplements Runnable { +public class TraceRunnable extends TraceDelegate implements Runnable { public TraceRunnable(TraceManager traceManager, Runnable delegate) { super(traceManager, delegate); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java index 3850fc9bd..df5cf1254 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java @@ -16,13 +16,13 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Trace; -import org.springframework.cloud.sleuth.TraceManager; - import com.netflix.hystrix.HystrixCommand; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixThreadPoolKey; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceManager; +import org.springframework.cloud.sleuth.trace.TraceContextHolder; /** * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting @@ -71,6 +71,7 @@ public abstract class TraceCommand extends HystrixCommand { @Override protected R run() throws Exception { + enforceThatHystrixThreadIsNotPolutedByPreviousTraces(); Trace trace = this.traceManager.startSpan(getCommandKey().name(), parentSpan); try { return doRun(); @@ -79,5 +80,10 @@ public abstract class TraceCommand extends HystrixCommand { } } + // TODO: Do more analysis why this is nor removed properly + private void enforceThatHystrixThreadIsNotPolutedByPreviousTraces() { + TraceContextHolder.removeCurrentTrace(); + } + public abstract R doRun() throws Exception; } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java index deba0548a..1e20fb5fb 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java @@ -16,17 +16,8 @@ package org.springframework.cloud.sleuth; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.ArrayList; -import java.util.List; - +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.cloud.sleuth.event.SpanAcquiredEvent; @@ -34,10 +25,19 @@ import org.springframework.cloud.sleuth.event.SpanReleasedEvent; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.sampler.IsTracingSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; +import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.JdkIdGenerator; +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.*; + /** * @author Spencer Gibb */ @@ -48,6 +48,16 @@ public class DefaultTraceManagerTests { public static final String IMPORTANT_WORK_2 = "important work 2"; public static final int NUM_SPANS = 3; + @Before + public void setup() { + TraceContextHolder.removeCurrentTrace(); + } + + @After + public void clean() { + TraceContextHolder.removeCurrentTrace(); + } + @Test public void tracingWorks() { ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTest.java index 860c93c9a..962ce2d80 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTest.java @@ -1,11 +1,6 @@ package org.springframework.cloud.sleuth.instrument; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.junit.Before; +import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @@ -18,6 +13,11 @@ import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.JdkIdGenerator; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.assertj.core.api.BDDAssertions.then; + @RunWith(MockitoJUnitRunner.class) public class TraceRunnableTest { @@ -25,8 +25,8 @@ public class TraceRunnableTest { TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); - @Before - public void init() { + @After + public void cleanup() { TraceContextHolder.removeCurrentTrace(); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java index 42111d8e2..996d0bd99 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java @@ -1,20 +1,5 @@ package org.springframework.cloud.sleuth.instrument.executor; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,10 +13,24 @@ import org.springframework.cloud.sleuth.event.SpanReleasedEvent; import org.springframework.cloud.sleuth.instrument.TraceRunnable; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; +import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.JdkIdGenerator; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.*; + public class TraceableExecutorServiceTests { private ApplicationEventPublisher publisher; private ExecutorService traceManagerableExecutorService; @@ -55,6 +54,7 @@ public class TraceableExecutorServiceTests { this.traceManager = null; this.traceManagerableExecutorService.shutdown(); this.executorService.shutdown(); + TraceContextHolder.removeCurrentTrace(); } @Test diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsITest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsITest.java index 407c48f3a..e5fd78347 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsITest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsITest.java @@ -1,9 +1,7 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; - -import java.util.concurrent.atomic.AtomicReference; - +import com.jayway.awaitility.Awaitility; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,8 +16,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.jayway.awaitility.Awaitility; -import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import java.util.concurrent.atomic.AtomicReference; + +import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { @@ -29,6 +28,7 @@ public class SpanPassingForHystrixViaAnnotationsITest { @Autowired HystrixCommandInvocationSpanCatcher hystrixCommandInvocationSpanCatcher; @Autowired TraceManager traceManager; + @Test public void should_set_span_on_an_hystrix_command_annotated_method() { Span span = givenASpanInCurrentThread(); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTest.java index c006080f9..0f8a32b5f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTest.java @@ -1,10 +1,9 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey; -import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey; -import static org.assertj.core.api.BDDAssertions.then; - +import com.netflix.hystrix.HystrixCommandKey; +import com.netflix.hystrix.HystrixThreadPoolProperties; import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.cloud.sleuth.MilliSpan; @@ -16,8 +15,9 @@ import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.JdkIdGenerator; -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixThreadPoolProperties; +import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey; +import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey; +import static org.assertj.core.api.BDDAssertions.then; public class TraceCommandTest { @@ -25,9 +25,20 @@ public class TraceCommandTest { TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); + @Before + public void setup() { + TraceContextHolder.removeCurrentTrace(); + } + + @After + public void cleanup() { + TraceContextHolder.removeCurrentTrace(); + } + @Test public void should_remove_span_from_thread_local_after_finishing_work() throws Exception { + TraceContextHolder.removeCurrentTrace(); Trace firstTraceFromHystrix = givenACommandWasExecuted(traceReturningCommand()); Trace secondTraceFromHystrix = whenCommandIsExecuted(traceReturningCommand()); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectITest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectITest.java index 1f7766a4f..e95be9463 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectITest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectITest.java @@ -1,19 +1,7 @@ package org.springframework.cloud.sleuth.instrument.web; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.matching; -import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; -import static java.util.concurrent.TimeUnit.SECONDS; -import static junitparams.JUnitParamsRunner.$; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.concurrent.Callable; - +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -38,10 +26,17 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.request.async.WebAsyncTask; -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; +import java.util.concurrent.Callable; -@SpringApplicationConfiguration(classes = {RestTemplateTraceAspectITest.CorrelationIdAspectSpecConfiguration.class}) +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static java.util.concurrent.TimeUnit.SECONDS; +import static junitparams.JUnitParamsRunner.$; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringApplicationConfiguration(classes = {RestTemplateTraceAspectITest.CorrelationIdAspectTestConfiguration.class}) @RunWith(JUnitParamsRunner.class) public class RestTemplateTraceAspectITest extends MvcWiremockITest { @@ -92,7 +87,7 @@ public class RestTemplateTraceAspectITest extends MvcWiremockITest { @EnableAsync @DefaultTestAutoConfiguration @Import(AspectTestingController.class) - public static class CorrelationIdAspectSpecConfiguration { + public static class CorrelationIdAspectTestConfiguration { } @RestController diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTest.java index aa97e4231..b330f76a3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTest.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.JdkIdGenerator; import org.springframework.web.bind.annotation.RequestHeader; @@ -42,9 +43,9 @@ import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = { TraceWebAutoConfiguration.class, - FeignTraceTest.TestConfiguration.class }) +@SpringApplicationConfiguration(classes = { FeignTraceTest.TestConfiguration.class }) @WebIntegrationTest(value = { "spring.application.name=fooservice" }, randomPort = true) +@DirtiesContext public class FeignTraceTest { @Autowired @@ -63,13 +64,13 @@ public class FeignTraceTest { } @Test - public void shouldWorkWhenNotTracing() { + public void shouldCreateANewSpanWhenNoPreviousTracingWasPresent() { // when ResponseEntity response = this.testFeignInterface.getNoTrace(); // then - then(getHeader(response, Trace.TRACE_ID_NAME)).isNull(); - then(this.listener.getEvents()).isEmpty(); + then(getHeader(response, Trace.TRACE_ID_NAME)).isNotNull(); + then(this.listener.getEvents()).isNotEmpty(); } @Test @@ -85,7 +86,6 @@ public class FeignTraceTest { // then then(getHeader(response, Trace.TRACE_ID_NAME)).isEqualTo(currentTraceId); - then(getHeader(response, Trace.PARENT_ID_NAME)).isEqualTo(currentParentId); then(this.listener.getEvents().size()).isEqualTo(2); } @@ -149,7 +149,7 @@ public class FeignTraceTest { @RequestMapping(value = "/notrace", method = RequestMethod.GET) public String notrace( @RequestHeader(name = Trace.TRACE_ID_NAME, required = false) String traceId) { - then(traceId).isNull(); + then(traceId).isNotNull(); return "OK"; } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java index 531560f3e..6737e121b 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java @@ -66,6 +66,7 @@ public class TraceRestTemplateInterceptorTests { new JdkIdGenerator(), this.publisher); this.template.setInterceptors(Arrays.asList( new TraceRestTemplateInterceptor(this.traces))); + TraceContextHolder.removeCurrentTrace(); } @After diff --git a/spring-cloud-sleuth-samples/pom.xml b/spring-cloud-sleuth-samples/pom.xml index f2d43386a..18008e54f 100644 --- a/spring-cloud-sleuth-samples/pom.xml +++ b/spring-cloud-sleuth-samples/pom.xml @@ -18,6 +18,7 @@ spring-cloud-sleuth-sample + spring-cloud-sleuth-sample-test-core spring-cloud-sleuth-sample-messaging spring-cloud-sleuth-sample-ribbon spring-cloud-sleuth-sample-zipkin @@ -26,17 +27,27 @@ - - - - - maven-deploy-plugin - - true - - - - - + + + + + maven-deploy-plugin + + true + + + + + + + + + + org.springframework.cloud + spring-cloud-sleuth-sample-test-core + ${project.version} + + + diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml index 74f4669cc..0de52460e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml @@ -39,6 +39,10 @@ + + 2.1.0 + + org.springframework.boot @@ -73,6 +77,21 @@ spring-boot-starter-test test + + org.assertj + assertj-core + test + + + com.jayway.awaitility + awaitility + test + + + org.springframework.cloud + spring-cloud-sleuth-sample-test-core + test + diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java index d7d1fa6d7..92adebffa 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java @@ -16,15 +16,14 @@ package sample; -import java.util.Random; - import lombok.SneakyThrows; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.sleuth.TraceManager; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import java.util.Random; + /** * @author Spencer Gibb */ diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/resources/logback.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/resources/logback.xml new file mode 100644 index 000000000..3cee99001 --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/resources/logback.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationDockerTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationDockerTests.java new file mode 100644 index 000000000..bf45879dd --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationDockerTests.java @@ -0,0 +1,114 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration; + +import com.github.kristofa.brave.SpanCollector; +import com.twitter.zipkin.gen.BinaryAnnotation; +import com.twitter.zipkin.gen.Span; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.JdkIdGenerator; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestTemplate; +import org.testcontainers.containers.DockerComposeContainer; +import sample.SampleMessagingApplication; +import tools.*; + +import java.io.File; +import java.util.Collection; + +import static org.assertj.core.api.BDDAssertions.then; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = { MessagingApplicationDockerTests.Config.class, SampleMessagingApplication.class }) +@WebIntegrationTest +@Slf4j +@Ignore("Ignored until working on profile") +public class MessagingApplicationDockerTests extends AbstractIntegrationTest { + + private static int port = 3381; + private static String sampleAppUrl = "http://localhost:" + port; + RestTemplate restTemplate = new AssertingRestTemplate(); + @Autowired IntegrationTestSpanCollector integrationTestSpanCollector; + + @ClassRule + public static DockerComposeContainer environment = + new DockerComposeContainer(new File("src/test/resources/docker-compose.yml")) + .withExposedService("rabbitmq_1", 5672); + + @After + public void cleanup() { + integrationTestSpanCollector.hashedSpans.clear(); + } + + @Test + public void should_propagate_spans_for_messaging() { + String traceId = new JdkIdGenerator().generateId().toString(); + + await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId)); + + await().until(() -> { + thenAllSpansHaveTraceIdEqualTo(traceId); + }); + } + + @Test + public void should_propagate_spans_for_messaging_with_async() { + String traceId = new JdkIdGenerator().generateId().toString(); + + await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/xform", traceId)); + + await().until(() -> { + thenAllSpansHaveTraceIdEqualTo(traceId); + thenThereIsAtLeastOneBinaryAnnotationWithKey("background-sleep-millis"); + }); + } + + private void thenThereIsAtLeastOneBinaryAnnotationWithKey(String binaryAnnotationKey) { + then(integrationTestSpanCollector.hashedSpans.stream() + .filter(Span::isSetBinary_annotations) + .map(Span::getBinary_annotations) + .flatMap(Collection::stream) + .filter(binaryAnnotation -> StringUtils.hasText(binaryAnnotation.getKey())) + .map(BinaryAnnotation::getKey) + .anyMatch(binaryAnnotationKey::equals)).isTrue(); + } + + private RequestSendingRunnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, String traceId) { + return new RequestSendingRunnable(restTemplate, endpoint, traceId); + } + + private void thenAllSpansHaveTraceIdEqualTo(String traceId) { + then(integrationTestSpanCollector.hashedSpans.stream().allMatch(span -> span.getTrace_id() == zipkinHashedTraceId(traceId))).isTrue(); + } + + @Configuration + static class Config { + @Bean SpanCollector integrationTestSpanCollector() { + return new IntegrationTestSpanCollector(); + } + } +} diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/resources/docker-compose.yml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/resources/docker-compose.yml new file mode 100644 index 000000000..deb4cf8d1 --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/resources/docker-compose.yml @@ -0,0 +1,5 @@ +rabbitmq: + image: rabbitmq:management + ports: + - 5672:5672 + - 15672:15672 \ No newline at end of file diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml new file mode 100644 index 000000000..478ddaf0a --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + spring-cloud-sleuth-sample-test-core + jar + Spring Cloud Sleuth Sample Test Core + Test classes for Spring Cloud Samples + + + org.springframework.cloud + spring-cloud-sleuth-samples + 1.0.0.BUILD-SNAPSHOT + .. + + + + + + + + maven-deploy-plugin + + true + + + + + + + + 2.1.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-integration + + + org.springframework.cloud + spring-cloud-sleuth-core + + + org.springframework.cloud + spring-cloud-sleuth-zipkin + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-actuator + + + org.projectlombok + lombok + + + junit + junit + + + org.springframework.boot + spring-boot-starter-test + test + + + org.assertj + assertj-core + compile + + + com.jayway.awaitility + awaitility + compile + + + org.testcontainers + docker-compose + 0.9.8 + compile + + + com.fasterxml.jackson.core + jackson-databind + ${testcontainers.jackson.version} + compile + + + com.fasterxml.jackson.core + jackson-core + ${testcontainers.jackson.version} + compile + + + com.fasterxml.jackson.core + jackson-annotations + ${testcontainers.jackson.version} + compile + + + + \ No newline at end of file diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java new file mode 100644 index 000000000..74c4f57aa --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tools; + +import com.jayway.awaitility.Awaitility; +import com.jayway.awaitility.core.ConditionFactory; +import org.junit.experimental.categories.Category; +import org.springframework.beans.factory.annotation.Value; + +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * @author Marcin Grzejszczak + */ +@Category(DockerTests.class) +abstract public class AbstractIntegrationTest { + + @Value("${test.pollinterval:1}") protected int pollInterval; + @Value("${test.timeout:1}") protected int timeout; + + protected ConditionFactory await() { + return Awaitility.await().pollInterval(pollInterval, SECONDS).atMost(timeout, SECONDS); + } + + protected long zipkinHashedTraceId(String string) { + long h = 1125899906842597L; + if (string == null) { + return h; + } + int len = string.length(); + + for (int i = 0; i < len; i++) { + h = 31 * h + string.charAt(i); + } + return h; + } +} diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java new file mode 100644 index 000000000..1d868b08a --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tools; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.*; + +import java.io.IOException; +import java.net.URI; + +/** + * + * RestTemplate that logs erroneous responses and throws AssertionsError on any connection issues + * + * @author Marcin Grzejszczak + */ +@Slf4j +public class AssertingRestTemplate extends RestTemplate { + + public AssertingRestTemplate() { + setErrorHandler(new DefaultResponseErrorHandler() { + @Override + public void handleError(ClientHttpResponse response) throws IOException { + if (hasError(response)) { + log.error("Response has status code [" + response.getStatusCode() + "] and text [" + response.getStatusText() + "])"); + } + } + }); + } + + @Override + protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { + try { + return super.doExecute(url, method, requestCallback, responseExtractor); + } catch (Exception e) { + log.error("Exception occurred while sending the message", e); + throw new AssertionError(e); + } + } +} diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/DockerTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/DockerTests.java new file mode 100644 index 000000000..c53a9fb99 --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/DockerTests.java @@ -0,0 +1,7 @@ +package tools; + +/** + * @author Marcin Grzejszczak + */ +interface DockerTests { +} diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/IntegrationTestSpanCollector.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/IntegrationTestSpanCollector.java new file mode 100644 index 000000000..e02b4cc6d --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/IntegrationTestSpanCollector.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tools; + +import com.github.kristofa.brave.LoggingSpanCollector; +import com.twitter.zipkin.gen.Span; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Span Collector that logs spans and adds Spans to a list + * + * @author Marcin Grzejszczak + */ +public class IntegrationTestSpanCollector extends LoggingSpanCollector { + + public List hashedSpans = Collections.synchronizedList(new LinkedList()); + + @Override + public void collect(Span span) { + super.collect(span); + hashedSpans.add(span); + } + +} diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java new file mode 100644 index 000000000..e69ec0139 --- /dev/null +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tools; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * Runnable that will send a request via the provide rest template to the + * given url. It will also append the provided TraceID as the request's header + * + * @author Marcin Grzejszczak + */ +@Slf4j +public class RequestSendingRunnable implements Runnable { + private final RestTemplate restTemplate; + private final String url; + private final String traceId; + + public RequestSendingRunnable(RestTemplate restTemplate, String url, String traceId) { + this.restTemplate = restTemplate; + this.url = url; + this.traceId = traceId; + } + + @Override + public void run() { + ResponseEntity responseEntity = restTemplate.exchange(requestWithTraceId(traceId), String.class); + then(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + log.info("Received the following response [{}]", responseEntity); + } + + private RequestEntity requestWithTraceId(String traceId) { + HttpHeaders headers = new HttpHeaders(); + headers.add(Trace.TRACE_ID_NAME, traceId); + URI uri = URI.create(url); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri); + log.info("Request [" + requestEntity + "] is ready"); + return requestEntity; + } +} diff --git a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java index 1fcf168bb..93dad95a3 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java +++ b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java @@ -19,6 +19,9 @@ package org.springframework.cloud.sleuth.zipkin.stream; import io.zipkin.BinaryAnnotation; import io.zipkin.Endpoint; import java.util.Collections; +import java.util.Comparator; +import java.util.Objects; + import org.junit.Test; import org.springframework.cloud.sleuth.MilliSpan; import org.springframework.cloud.sleuth.stream.Host; @@ -70,8 +73,9 @@ public class ZipkinMessageListenerTests { public void spanWithoutAnnotationsLogsComponent() { io.zipkin.Span result = ZipkinMessageListener.convert(span, host); - assertThat(result.binaryAnnotations) - .containsOnly(BinaryAnnotation.create("lc", span.getProcessId(), endpoint)); + assertThat(result.binaryAnnotations).hasSize(1); + assertThat(result.binaryAnnotations.get(0)).isEqualToComparingFieldByField( + BinaryAnnotation.create("lc", span.getProcessId().toLowerCase(), endpoint)); } // TODO: "unknown" bc process id, documented as not nullable, is null in some tests. diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java index fe76d85f8..d1ce68e55 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java @@ -127,8 +127,7 @@ public class ZipkinSpanListenerTests { Trace context = this.traceManager.startSpan("foo"); this.traceManager.close(context); assertEquals(1, this.test.spans.size()); - assertThat(this.test.spans.get(0).getBinary_annotations()) - .extracting("host.service_name") + assertThat(this.test.spans.get(0).getBinary_annotations().get(0).getHost().getService_name()) .isEqualTo("unknown"); // TODO: "unknown" bc process id, documented as not nullable, is null. }