or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdexporters.mdindex.mdjunit-integration.mdtest-builders.mdutilities.md

junit-integration.mddocs/

0

# JUnit Integration

1

2

JUnit 4 and JUnit 5 extensions that automatically set up OpenTelemetry SDK for testing with in-memory exporters and convenient access to collected telemetry data. These extensions handle the lifecycle of OpenTelemetry configuration and provide easy access to captured spans, metrics, and logs.

3

4

## Capabilities

5

6

### JUnit 5 Extension

7

8

JUnit 5 extension that configures OpenTelemetry SDK with in-memory exporters and provides convenient access to collected telemetry data.

9

10

```java { .api }

11

class OpenTelemetryExtension implements BeforeEachCallback, BeforeAllCallback, AfterAllCallback {

12

// Factory method

13

static OpenTelemetryExtension create();

14

15

// OpenTelemetry access

16

OpenTelemetry getOpenTelemetry();

17

18

// Collected data access

19

List<SpanData> getSpans();

20

List<MetricData> getMetrics();

21

List<LogRecordData> getLogRecords();

22

23

// Assertion helper

24

TracesAssert assertTraces();

25

26

// Data management

27

void clearSpans();

28

void clearMetrics();

29

void clearLogRecords();

30

}

31

```

32

33

Usage examples:

34

35

```java

36

import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension;

37

import org.junit.jupiter.api.Test;

38

import org.junit.jupiter.api.extension.RegisterExtension;

39

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.*;

40

41

class MyServiceTest {

42

43

@RegisterExtension

44

static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();

45

46

@Test

47

void testServiceOperation() {

48

// Get the configured OpenTelemetry instance

49

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

50

51

// Initialize your service with the test OpenTelemetry

52

MyService service = new MyService(openTelemetry);

53

54

// Execute the operation that should create telemetry

55

service.performOperation("test-input");

56

57

// Validate collected spans

58

assertThat(otelTesting.getSpans())

59

.hasSize(2)

60

.satisfiesExactly(

61

span -> assertThat(span)

62

.hasName("service.operation")

63

.hasAttribute(AttributeKey.stringKey("input"), "test-input"),

64

span -> assertThat(span)

65

.hasName("database.query")

66

.hasKind(SpanKind.CLIENT)

67

);

68

69

// Validate collected metrics

70

assertThat(otelTesting.getMetrics())

71

.hasSize(1)

72

.first()

73

.hasName("operation.duration")

74

.hasDoubleGaugeSatisfying(gauge ->

75

gauge.hasPointsSatisfying(point ->

76

point.hasValue(greaterThan(0.0))

77

)

78

);

79

80

// Validate collected logs

81

assertThat(otelTesting.getLogRecords())

82

.hasSize(1)

83

.first()

84

.hasBody("Operation completed successfully")

85

.hasSeverity(Severity.INFO);

86

}

87

88

@Test

89

void testWithTraceAssertions() {

90

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

91

MyService service = new MyService(openTelemetry);

92

93

service.performNestedOperations();

94

95

// Use the built-in trace assertions

96

otelTesting.assertTraces()

97

.hasTracesSatisfyingExactly(

98

trace -> trace.hasSpansSatisfyingExactly(

99

span -> assertThat(span).hasName("parent.operation"),

100

span -> assertThat(span).hasName("child.operation.1"),

101

span -> assertThat(span).hasName("child.operation.2")

102

)

103

);

104

}

105

106

@Test

107

void testDataClearing() {

108

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

109

MyService service = new MyService(openTelemetry);

110

111

// First operation

112

service.performOperation("first");

113

assertThat(otelTesting.getSpans()).hasSize(1);

114

115

// Clear data and perform second operation

116

otelTesting.clearSpans();

117

service.performOperation("second");

118

assertThat(otelTesting.getSpans()).hasSize(1);

119

assertThat(otelTesting.getSpans().get(0))

120

.hasAttribute(AttributeKey.stringKey("input"), "second");

121

}

122

}

123

```

124

125

### JUnit 4 Rule

126

127

JUnit 4 rule that provides the same functionality as the JUnit 5 extension for projects using JUnit 4.

128

129

```java { .api }

130

class OpenTelemetryRule extends ExternalResource {

131

// Factory method

132

static OpenTelemetryRule create();

133

134

// OpenTelemetry access (identical to JUnit 5 extension)

135

OpenTelemetry getOpenTelemetry();

136

137

// Collected data access

138

List<SpanData> getSpans();

139

List<MetricData> getMetrics();

140

List<LogRecordData> getLogRecords();

141

142

// Data management

143

void clearSpans();

144

void clearMetrics();

145

void clearLogRecords();

146

}

147

```

148

149

Usage examples:

150

151

```java

152

import io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule;

153

import org.junit.Rule;

154

import org.junit.Test;

155

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.*;

156

157

public class MyServiceTest {

158

159

@Rule

160

public final OpenTelemetryRule otelTesting = OpenTelemetryRule.create();

161

162

@Test

163

public void testServiceOperation() {

164

// Get the configured OpenTelemetry instance

165

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

166

167

// Initialize your service with the test OpenTelemetry

168

MyService service = new MyService(openTelemetry);

169

170

// Execute the operation

171

service.performOperation("test-input");

172

173

// Validate collected data

174

assertThat(otelTesting.getSpans())

175

.hasSize(1)

176

.first()

177

.hasName("service.operation")

178

.hasAttribute(AttributeKey.stringKey("input"), "test-input");

179

}

180

181

@Test

182

public void testMultipleOperations() {

183

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

184

MyService service = new MyService(openTelemetry);

185

186

// Perform multiple operations

187

service.performOperation("first");

188

service.performOperation("second");

189

190

// Validate all collected spans

191

assertThat(otelTesting.getSpans())

192

.hasSize(2)

193

.extracting(SpanData::getName)

194

.containsExactly("service.operation", "service.operation");

195

196

// Validate attributes of specific spans

197

assertThat(otelTesting.getSpans().get(0))

198

.hasAttribute(AttributeKey.stringKey("input"), "first");

199

assertThat(otelTesting.getSpans().get(1))

200

.hasAttribute(AttributeKey.stringKey("input"), "second");

201

}

202

}

203

```

204

205

## Configuration and Lifecycle

206

207

### Automatic Configuration

208

209

Both the JUnit 5 extension and JUnit 4 rule automatically configure:

210

211

- **SdkTracerProvider** with InMemorySpanExporter

212

- **SdkMeterProvider** with InMemoryMetricReader

213

- **SdkLoggerProvider** with InMemoryLogRecordExporter

214

- **Resource** with basic service information

215

- **Batch processors** for efficient data collection

216

217

### Lifecycle Management

218

219

The extensions handle the complete lifecycle:

220

221

1. **Setup** (before all/each test): Initialize OpenTelemetry SDK with testing configuration

222

2. **Execution**: Provide configured OpenTelemetry instance to tests

223

3. **Cleanup** (after all tests): Shutdown SDK components properly

224

4. **Data clearing**: Automatic clearing between tests (JUnit 5) or manual clearing (both)

225

226

### Data Collection Behavior

227

228

```java

229

// Data collection happens automatically during test execution

230

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

231

232

// Create telemetry in your code

233

Tracer tracer = openTelemetry.getTracer("test");

234

Span span = tracer.spanBuilder("operation").startSpan();

235

span.end();

236

237

// Data is immediately available for assertions

238

List<SpanData> spans = otelTesting.getSpans(); // Contains the created span

239

```

240

241

## Advanced Usage Patterns

242

243

### Custom Service Configuration

244

245

```java

246

@Test

247

void testWithCustomConfiguration() {

248

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

249

250

// Configure your service with additional resources or instrumentation

251

MyService service = MyService.builder()

252

.withOpenTelemetry(openTelemetry)

253

.withResource(Resource.getDefault().merge(

254

Resource.builder()

255

.put(ResourceAttributes.SERVICE_NAME, "test-service")

256

.put(ResourceAttributes.SERVICE_VERSION, "1.0.0")

257

.build()))

258

.build();

259

260

service.performOperation();

261

262

// Validate resource attributes

263

assertThat(otelTesting.getSpans())

264

.first()

265

.hasResourceSatisfying(resource ->

266

assertThat(resource)

267

.hasAttribute(ResourceAttributes.SERVICE_NAME, "test-service")

268

.hasAttribute(ResourceAttributes.SERVICE_VERSION, "1.0.0")

269

);

270

}

271

```

272

273

### Testing Error Scenarios

274

275

```java

276

@Test

277

void testErrorHandling() {

278

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

279

MyService service = new MyService(openTelemetry);

280

281

// Trigger an error condition

282

assertThrows(ServiceException.class, () ->

283

service.performOperation("invalid-input"));

284

285

// Validate error span

286

assertThat(otelTesting.getSpans())

287

.first()

288

.hasName("service.operation")

289

.hasStatusSatisfying(status ->

290

status.hasCode(StatusCode.ERROR)

291

.hasDescription("Invalid input provided")

292

)

293

.hasException(ServiceException.class);

294

295

// Validate error logs

296

assertThat(otelTesting.getLogRecords())

297

.first()

298

.hasSeverity(Severity.ERROR)

299

.hasBody(containsString("Failed to process input"));

300

}

301

```

302

303

### Parameterized Tests

304

305

```java

306

@ParameterizedTest

307

@ValueSource(strings = {"input1", "input2", "input3"})

308

void testParameterizedOperations(String input) {

309

OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();

310

MyService service = new MyService(openTelemetry);

311

312

service.performOperation(input);

313

314

assertThat(otelTesting.getSpans())

315

.hasSize(1)

316

.first()

317

.hasAttribute(AttributeKey.stringKey("input"), input);

318

319

// Clear data for next parameterized test

320

otelTesting.clearSpans();

321

}

322

```

323

324

## Types

325

326

```java { .api }

327

// JUnit 5 callback interfaces

328

interface BeforeEachCallback {

329

void beforeEach(ExtensionContext context) throws Exception;

330

}

331

332

interface BeforeAllCallback {

333

void beforeAll(ExtensionContext context) throws Exception;

334

}

335

336

interface AfterAllCallback {

337

void afterAll(ExtensionContext context) throws Exception;

338

}

339

340

// JUnit 4 rule base class

341

abstract class ExternalResource implements TestRule {

342

protected void before() throws Throwable;

343

protected void after();

344

}

345

346

// OpenTelemetry SDK components configured by extensions

347

interface OpenTelemetry {

348

TracerProvider getTracerProvider();

349

MeterProvider getMeterProvider();

350

LoggerProvider getLoggerProvider();

351

}

352

353

// Data types returned by extensions

354

interface SpanData { /* Completed span data */ }

355

interface MetricData { /* Metric measurement data */ }

356

interface LogRecordData { /* Log record data */ }

357

358

// Assertion helper type

359

class TracesAssert extends AbstractAssert<TracesAssert, Collection<List<SpanData>>> {

360

TracesAssert hasTracesSatisfyingExactly(Consumer<TraceAssert>... assertions);

361

}

362

```