Search code examples
springspring-cloudspring-cloud-config

Error with Zipkin in unit test (cannot mock Span.baggageItems)


I am getting this error when I try to run the unitTest in my spring boot application.

java.lang.NullPointerException: null
at org.springframework.cloud.sleuth.Span.baggageItems(Span.java:381)
at org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanInjector.inject(ZipkinHttpSpanInjector.java:27)
at org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanInjector.inject(ZipkinHttpSpanInjector.java:15)
at org.springframework.cloud.sleuth.instrument.web.client.AbstractTraceHttpRequestInterceptor.publishStartEvent(AbstractTraceHttpRequestInterceptor.java:60)
at org.springframework.cloud.sleuth.instrument.web.client.TraceRestTemplateInterceptor.intercept(TraceRestTemplateInterceptor.java:52)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:86)

I notice that I only get this error when I use this version for spring-cloud-dependencies:

<spring-cloud.version>Dalston.RELEASE</spring-cloud.version>

but if I use this previous version:

<spring-cloud.version>Camden.SR6</spring-cloud.version>

everything works as I expect

What can I do in order to avoid this error with the last version?

The unit tests are extended this class in order to mock the SpanAccessor

public class AbstractSpanAccessorTest {

@MockBean
private Tracer tracer;

@MockBean
private Span span;

private Random random = new Random();

@Before
public void mockSpan() {
    long id = createId();
    Span spanMock = Span.builder().name("mock").traceId(id).spanId(id).build();
    doReturn(spanMock.traceIdString()).when(span).traceIdString();
    doReturn(span).when(tracer).getCurrentSpan();
    doReturn(span).when(tracer).createSpan(anyString());
}

private long createId() {
    return random.nextLong();
}

}


Solution

  • Why are you mocking a span? This makes absolutely no sense. Also a Span is never a bean. You already create a normal span via a builder and you should leave that. Assuming that you have set up the Boot context property and you want to mock out tracer bean you should do the following

    public class AbstractSpanAccessorTest {
    @MockBean
    private Tracer tracer;
    
    private Random random = new Random();
    
    @Before
    public void mockSpan() {
      long id = createId();
      Span spanMock = Span.builder().name("mock").traceId(id).spanId(id).build();
      doReturn(spanMock).when(tracer).getCurrentSpan();
      doReturn(spanMock).when(tracer).createSpan(anyString());
    }
    
    private long createId() {
      return random.nextLong();
    }
    }