[#128] Added an integration test
This commit is contained in:
@@ -60,6 +60,11 @@ public class SampleMessagingApplication {
|
||||
return msg;
|
||||
}
|
||||
|
||||
@RequestMapping("/foo")
|
||||
public String foo() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
@RequestMapping("/xform")
|
||||
public String xform() {
|
||||
String msg = "Hello";
|
||||
|
||||
@@ -18,9 +18,13 @@ package sample;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -28,11 +32,19 @@ import org.springframework.messaging.Message;
|
||||
*/
|
||||
@MessageEndpoint
|
||||
@Slf4j
|
||||
public class SampleService {
|
||||
public class SampleService implements
|
||||
ApplicationListener<EmbeddedServletContainerInitializedEvent> {
|
||||
@Autowired private RestTemplate restTemplate;
|
||||
private int port;
|
||||
|
||||
@ServiceActivator(inputChannel="messages")
|
||||
public void log(Message<?> message) {
|
||||
log.info("Received: " + message);
|
||||
this.restTemplate.getForObject("http://localhost:" + this.port + "/foo", String.class);
|
||||
}
|
||||
|
||||
@Override public void onApplicationEvent(
|
||||
EmbeddedServletContainerInitializedEvent event) {
|
||||
this.port = event.getEmbeddedServletContainer().getPort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@ import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import sample.SampleMessagingApplication;
|
||||
import tools.AbstractIntegrationTest;
|
||||
import zipkin.Span;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
@@ -51,7 +53,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_propagate_spans_for_messaging() {
|
||||
public void should_have_passed_trace_id_when_message_is_about_to_be_sent() {
|
||||
long traceId = new Random().nextLong();
|
||||
|
||||
await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId));
|
||||
@@ -62,7 +64,20 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_propagate_spans_for_messaging_with_async() {
|
||||
public void should_have_passed_trace_id_and_generate_new_span_id_when_message_is_about_to_be_sent() {
|
||||
long traceId = new Random().nextLong();
|
||||
long spanId = new Random().nextLong();
|
||||
|
||||
await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId, spanId));
|
||||
|
||||
await().until(() -> {
|
||||
thenAllSpansHaveTraceIdEqualTo(traceId);
|
||||
thenTheLastSpansParentHasIdEqualToFirstSpansId();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_have_passed_trace_id_with_annotations_in_async_thread_when_message_is_about_to_be_sent() {
|
||||
long traceId = new Random().nextLong();
|
||||
|
||||
await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/xform", traceId));
|
||||
@@ -84,6 +99,16 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
then(this.integrationTestSpanCollector.hashedSpans.stream().allMatch(span -> span.traceId == traceId)).isTrue();
|
||||
}
|
||||
|
||||
private void thenTheLastSpansParentHasIdEqualToFirstSpansId() {
|
||||
Optional<Span> firstSpan = this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> "http/".equals(span.name) && span.parentId != null).findFirst();
|
||||
Optional<Span> lastSpan = this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> "http/foo".equals(span.name)).findFirst();
|
||||
then(firstSpan.isPresent()).isTrue();
|
||||
then(lastSpan.isPresent()).isTrue();
|
||||
then(lastSpan.get().parentId).isEqualTo(firstSpan.get().id);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class IntegrationSpanCollectorConfig {
|
||||
@Bean
|
||||
|
||||
@@ -18,6 +18,9 @@ package tools;
|
||||
import com.jayway.awaitility.Awaitility;
|
||||
import com.jayway.awaitility.core.ConditionFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import zipkin.Codec;
|
||||
@@ -40,6 +43,16 @@ public abstract class AbstractIntegrationTest {
|
||||
protected static int timeout = 20;
|
||||
protected RestTemplate restTemplate = new AssertingRestTemplate();
|
||||
|
||||
@Before
|
||||
public void clearSpanBefore() {
|
||||
SpanContextHolder.removeCurrentSpan();
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearSpanAfter() {
|
||||
SpanContextHolder.removeCurrentSpan();
|
||||
}
|
||||
|
||||
public static ConditionFactory await() {
|
||||
return Awaitility.await().pollInterval(pollInterval, SECONDS).atMost(timeout, SECONDS);
|
||||
}
|
||||
@@ -102,7 +115,11 @@ public abstract class AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId) {
|
||||
return new RequestSendingRunnable(this.restTemplate, endpoint, traceId);
|
||||
return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, null);
|
||||
}
|
||||
|
||||
protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId, Long spanId) {
|
||||
return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, spanId);
|
||||
}
|
||||
|
||||
protected Runnable allSpansWereRegisteredInZipkinWithTraceIdEqualTo(long traceId) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@@ -39,25 +40,30 @@ public class RequestSendingRunnable implements Runnable {
|
||||
private final RestTemplate restTemplate;
|
||||
private final String url;
|
||||
private final long traceId;
|
||||
private final Random random = new Random();
|
||||
private final long spanId;
|
||||
|
||||
public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId) {
|
||||
public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId,
|
||||
Long spanId) {
|
||||
this.restTemplate = restTemplate;
|
||||
this.url = url;
|
||||
this.traceId = traceId;
|
||||
this.spanId = spanId != null ? spanId : this.random.nextLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("Sending the request to url [{}] with trace id in headers [{}]", this.url, this.traceId);
|
||||
ResponseEntity<String> responseEntity =
|
||||
this.restTemplate.exchange(requestWithTraceId(this.traceId), String.class);
|
||||
this.restTemplate.exchange(requestWithTraceId(), String.class);
|
||||
then(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
log.info("Received the following response [{}]", responseEntity);
|
||||
}
|
||||
|
||||
private RequestEntity requestWithTraceId(long traceId) {
|
||||
private RequestEntity requestWithTraceId() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(Span.TRACE_ID_NAME, Span.toHex(traceId));
|
||||
headers.add(Span.TRACE_ID_NAME, Span.toHex(this.traceId));
|
||||
headers.add(Span.SPAN_ID_NAME, Span.toHex(this.spanId));
|
||||
URI uri = URI.create(this.url);
|
||||
RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri);
|
||||
log.info("Request [" + requestEntity + "] is ready");
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package integration;
|
||||
|
||||
import example.ZipkinStreamServerApplication;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -30,6 +30,7 @@ import org.springframework.cloud.sleuth.stream.SleuthSink;
|
||||
import org.springframework.cloud.sleuth.stream.Spans;
|
||||
import org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -47,29 +48,34 @@ public class ZipkinStreamTests extends AbstractIntegrationTest {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int zipkinServerPort = 9411;
|
||||
long traceId = new Random().nextLong();
|
||||
long spanId = new Random().nextLong();
|
||||
|
||||
@Autowired
|
||||
@Qualifier(SleuthSink.INPUT)
|
||||
private MessageChannel input;
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void should_propagate_spans_to_zipkin() {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
await().until(zipkinServerIsUp());
|
||||
}
|
||||
|
||||
long traceId = new Random().nextLong();
|
||||
Span span = Span.builder().traceId(traceId).spanId(traceId).name("test")
|
||||
.build();
|
||||
@Test
|
||||
public void should_propagate_spans_to_zipkin() {
|
||||
Span span = Span.builder().traceId(traceId).spanId(spanId).name("test").build();
|
||||
span.tag(getRequiredBinaryAnnotationName(), "10131");
|
||||
|
||||
this.input.send(MessageBuilder.withPayload(
|
||||
new Spans(new Host(getAppName(), "127.0.0.1", 8080), Collections.singletonList(span)))
|
||||
.build());
|
||||
this.input.send(messageWithSpan(span));
|
||||
|
||||
await().until(allSpansWereRegisteredInZipkinWithTraceIdEqualTo(traceId));
|
||||
}
|
||||
|
||||
private Message<Spans> messageWithSpan(Span span) {
|
||||
return MessageBuilder.withPayload(
|
||||
new Spans(new Host(getAppName(), "127.0.0.1", 8080), Collections.singletonList(span)))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getZipkinServerPort() {
|
||||
return this.zipkinServerPort;
|
||||
|
||||
Reference in New Issue
Block a user