or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

http-testing.mdindex.mdlaunchers.mdtest-annotations.mdtest-context.mdtest-resources.mdutilities.md

test-context.mddocs/

0

# Test Context and Status

1

2

Access to test execution context, Dev Services properties, and test failure status for advanced test scenarios and resource cleanup. These components provide deep integration with the Quarkus test lifecycle and development services.

3

4

## Capabilities

5

6

### TestStatus Class

7

8

Represents test execution status with access to failure information for conditional resource cleanup and debugging.

9

10

```java { .api }

11

public class TestStatus {

12

public TestStatus(Throwable testErrorCause) {}

13

public Throwable getTestErrorCause() {}

14

public boolean isTestFailed() {}

15

}

16

```

17

18

**Usage in Test Resources:**

19

```java

20

public class LoggingTestResource implements QuarkusTestResourceLifecycleManager {

21

private TestStatus testStatus;

22

23

@Override

24

public void setContext(Context context) {

25

this.testStatus = context.getTestStatus();

26

}

27

28

@Override

29

public void stop() {

30

if (testStatus.isTestFailed()) {

31

// Capture additional logs for failed tests

32

captureFailureLogs();

33

34

Throwable cause = testStatus.getTestErrorCause();

35

if (cause != null) {

36

System.err.println("Test failed with: " + cause.getMessage());

37

cause.printStackTrace();

38

}

39

}

40

}

41

42

private void captureFailureLogs() {

43

// Implementation to capture logs, database state, etc.

44

System.out.println("Capturing failure diagnostics...");

45

}

46

}

47

```

48

49

### DevServicesContext Interface

50

51

Provides access to Dev Services properties and container networking information for test resource coordination.

52

53

```java { .api }

54

public interface DevServicesContext {

55

Map<String, String> devServicesProperties();

56

Optional<String> containerNetworkId();

57

58

interface ContextAware {

59

void setIntegrationTestContext(DevServicesContext context);

60

}

61

}

62

```

63

64

**Usage Example:**

65

```java

66

public class DatabaseAwareTestResource implements QuarkusTestResourceLifecycleManager,

67

DevServicesContext.ContextAware {

68

private DevServicesContext devServicesContext;

69

70

@Override

71

public void setIntegrationTestContext(DevServicesContext context) {

72

this.devServicesContext = context;

73

}

74

75

@Override

76

public Map<String, String> start() {

77

// Access Dev Services database properties

78

Map<String, String> devServicesProps = devServicesContext.devServicesProperties();

79

String dbUrl = devServicesProps.get("quarkus.datasource.jdbc.url");

80

81

if (dbUrl != null) {

82

System.out.println("Using Dev Services database: " + dbUrl);

83

84

// Use the same network for additional containers

85

Optional<String> networkId = devServicesContext.containerNetworkId();

86

if (networkId.isPresent()) {

87

return configureWithNetwork(networkId.get());

88

}

89

}

90

91

return Map.of();

92

}

93

94

private Map<String, String> configureWithNetwork(String networkId) {

95

// Configure additional test containers to use the same network

96

// This allows containers to communicate with Dev Services

97

GenericContainer<?> additionalService = new GenericContainer<>("redis:7")

98

.withNetwork(Network.newNetwork())

99

.withExposedPorts(6379);

100

101

additionalService.start();

102

103

return Map.of(

104

"quarkus.redis.hosts", "redis://localhost:" + additionalService.getMappedPort(6379)

105

);

106

}

107

}

108

```

109

110

### ListeningAddress Class

111

112

Represents server listening address information for test URL construction and service discovery.

113

114

```java { .api }

115

public class ListeningAddress {

116

public ListeningAddress(Integer port, String protocol) {}

117

public Integer getPort() {}

118

public String getProtocol() {}

119

public boolean isSsl() {}

120

}

121

```

122

123

**Usage Example:**

124

```java

125

public class ServiceDiscoveryTest {

126

@Test

127

public void testServiceEndpoints() {

128

// Get application listening addresses

129

ListeningAddress httpAddress = new ListeningAddress(8080, "http");

130

ListeningAddress httpsAddress = new ListeningAddress(8443, "https");

131

132

// Test HTTP endpoint

133

assertFalse(httpAddress.isSsl());

134

assertEquals("http", httpAddress.getProtocol());

135

136

String httpUrl = httpAddress.getProtocol() + "://localhost:" + httpAddress.getPort();

137

given()

138

.baseUri(httpUrl)

139

.when()

140

.get("/health")

141

.then()

142

.statusCode(200);

143

144

// Test HTTPS endpoint

145

assertTrue(httpsAddress.isSsl());

146

assertEquals("https", httpsAddress.getProtocol());

147

148

String httpsUrl = httpsAddress.getProtocol() + "://localhost:" + httpsAddress.getPort();

149

given()

150

.baseUri(httpsUrl)

151

.relaxedHTTPSValidation()

152

.when()

153

.get("/health")

154

.then()

155

.statusCode(200);

156

}

157

}

158

```

159

160

## Advanced Usage Patterns

161

162

### Conditional Test Resource Behavior

163

164

Using test status for conditional resource management:

165

166

```java

167

public class ConditionalCleanupResource implements QuarkusTestResourceLifecycleManager {

168

private ExternalService externalService;

169

private TestStatus testStatus;

170

171

@Override

172

public void setContext(Context context) {

173

this.testStatus = context.getTestStatus();

174

}

175

176

@Override

177

public Map<String, String> start() {

178

externalService = new ExternalService();

179

externalService.start();

180

181

return Map.of(

182

"external.service.url", externalService.getUrl()

183

);

184

}

185

186

@Override

187

public void stop() {

188

if (testStatus.isTestFailed()) {

189

// Preserve resources for debugging

190

System.out.println("Test failed - preserving external service for debugging");

191

System.out.println("Service URL: " + externalService.getUrl());

192

System.out.println("Admin URL: " + externalService.getAdminUrl());

193

194

// Optionally create debug snapshot

195

externalService.createDebugSnapshot();

196

} else {

197

// Normal cleanup

198

externalService.stop();

199

}

200

}

201

}

202

```

203

204

### Dev Services Integration

205

206

Integrating with existing Dev Services containers:

207

208

```java

209

public class DevServicesIntegrationResource implements QuarkusTestResourceLifecycleManager,

210

DevServicesContext.ContextAware {

211

private DevServicesContext context;

212

private GenericContainer<?> additionalContainer;

213

214

@Override

215

public void setIntegrationTestContext(DevServicesContext context) {

216

this.context = context;

217

}

218

219

@Override

220

public Map<String, String> start() {

221

Map<String, String> config = new HashMap<>();

222

223

// Get Dev Services properties

224

Map<String, String> devProps = context.devServicesProperties();

225

226

// Check if Dev Services PostgreSQL is running

227

String dbUrl = devProps.get("quarkus.datasource.jdbc.url");

228

if (dbUrl != null && dbUrl.contains("postgresql")) {

229

// Start additional container in same network

230

Optional<String> networkId = context.containerNetworkId();

231

232

if (networkId.isPresent()) {

233

additionalContainer = new GenericContainer<>("adminer:4")

234

.withNetwork(Network.newNetwork())

235

.withExposedPorts(8080)

236

.withEnv("ADMINER_DEFAULT_SERVER", extractHostFromUrl(dbUrl));

237

238

additionalContainer.start();

239

240

config.put("adminer.url",

241

"http://localhost:" + additionalContainer.getMappedPort(8080));

242

}

243

}

244

245

return config;

246

}

247

248

@Override

249

public void stop() {

250

if (additionalContainer != null) {

251

additionalContainer.stop();

252

}

253

}

254

255

private String extractHostFromUrl(String jdbcUrl) {

256

// Extract hostname from JDBC URL for container networking

257

return jdbcUrl.replaceAll(".*//([^:/]+).*", "$1");

258

}

259

}

260

```

261

262

### Test Profile Context

263

264

Using test profile information for conditional behavior:

265

266

```java

267

public class ProfileAwareResource implements QuarkusTestResourceLifecycleManager {

268

private String testProfile;

269

270

@Override

271

public void setContext(Context context) {

272

this.testProfile = context.testProfile();

273

}

274

275

@Override

276

public Map<String, String> start() {

277

Map<String, String> config = new HashMap<>();

278

279

switch (testProfile) {

280

case "integration":

281

// Start full external services

282

config.putAll(startIntegrationServices());

283

break;

284

285

case "performance":

286

// Start monitoring and metrics services

287

config.putAll(startPerformanceServices());

288

break;

289

290

case "security":

291

// Start security test services

292

config.putAll(startSecurityServices());

293

break;

294

295

default:

296

// Minimal setup for unit tests

297

config.putAll(startMinimalServices());

298

}

299

300

return config;

301

}

302

303

private Map<String, String> startIntegrationServices() {

304

// Start database, message broker, external APIs

305

return Map.of(

306

"postgres.url", startPostgres(),

307

"kafka.url", startKafka(),

308

"external.api.url", startMockAPI()

309

);

310

}

311

312

private Map<String, String> startPerformanceServices() {

313

// Start monitoring stack

314

return Map.of(

315

"prometheus.url", startPrometheus(),

316

"grafana.url", startGrafana()

317

);

318

}

319

320

// Additional profile-specific configurations...

321

}

322

```

323

324

### Multi-Container Coordination

325

326

Coordinating multiple containers with shared networking:

327

328

```java

329

public class MultiContainerResource implements QuarkusTestResourceLifecycleManager,

330

DevServicesContext.ContextAware {

331

private DevServicesContext context;

332

private Network sharedNetwork;

333

private GenericContainer<?> databaseContainer;

334

private GenericContainer<?> cacheContainer;

335

private GenericContainer<?> messageContainer;

336

337

@Override

338

public void setIntegrationTestContext(DevServicesContext context) {

339

this.context = context;

340

}

341

342

@Override

343

public Map<String, String> start() {

344

// Create or reuse network

345

Optional<String> existingNetwork = context.containerNetworkId();

346

if (existingNetwork.isPresent()) {

347

// Use Dev Services network

348

sharedNetwork = Network.newNetwork();

349

} else {

350

// Create new network

351

sharedNetwork = Network.newNetwork();

352

}

353

354

// Start coordinated containers

355

Map<String, String> config = new HashMap<>();

356

config.putAll(startDatabase());

357

config.putAll(startCache());

358

config.putAll(startMessageBroker());

359

360

return config;

361

}

362

363

private Map<String, String> startDatabase() {

364

databaseContainer = new PostgreSQLContainer<>("postgres:13")

365

.withNetwork(sharedNetwork)

366

.withNetworkAliases("postgres")

367

.withDatabaseName("testdb");

368

369

databaseContainer.start();

370

371

return Map.of(

372

"quarkus.datasource.jdbc.url", databaseContainer.getJdbcUrl(),

373

"quarkus.datasource.username", databaseContainer.getUsername(),

374

"quarkus.datasource.password", databaseContainer.getPassword()

375

);

376

}

377

378

private Map<String, String> startCache() {

379

cacheContainer = new GenericContainer<>("redis:7")

380

.withNetwork(sharedNetwork)

381

.withNetworkAliases("redis")

382

.withExposedPorts(6379);

383

384

cacheContainer.start();

385

386

return Map.of(

387

"quarkus.redis.hosts", "redis://localhost:" + cacheContainer.getMappedPort(6379)

388

);

389

}

390

391

private Map<String, String> startMessageBroker() {

392

messageContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0"))

393

.withNetwork(sharedNetwork)

394

.withNetworkAliases("kafka");

395

396

messageContainer.start();

397

398

return Map.of(

399

"kafka.bootstrap.servers", messageContainer.getBootstrapServers()

400

);

401

}

402

403

@Override

404

public void stop() {

405

if (messageContainer != null) messageContainer.stop();

406

if (cacheContainer != null) cacheContainer.stop();

407

if (databaseContainer != null) databaseContainer.stop();

408

if (sharedNetwork != null) sharedNetwork.close();

409

}

410

}

411

```

412

413

### Test Startup Notification Interfaces

414

415

Interfaces for detecting when integration tests and native images have started, particularly useful for non-HTTP based applications.

416

417

```java { .api }

418

public interface IntegrationTestStartedNotifier {

419

Result check(Context context);

420

421

interface Context {

422

Path logFile();

423

}

424

425

interface Result {

426

boolean isStarted();

427

boolean isSsl();

428

429

final class NotStarted implements Result {

430

public static final NotStarted INSTANCE = new NotStarted();

431

public boolean isStarted() { return false; }

432

public boolean isSsl() { return false; }

433

}

434

}

435

}

436

437

@Deprecated

438

public interface NativeImageStartedNotifier {

439

boolean isNativeImageStarted();

440

}

441

```

442

443

**Usage Example - Custom Integration Test Notifier:**

444

445

```java

446

public class CustomStartupNotifier implements IntegrationTestStartedNotifier {

447

@Override

448

public Result check(Context context) {

449

Path logFile = context.logFile();

450

451

try {

452

String logContent = Files.readString(logFile);

453

454

// Check for application startup indicators

455

if (logContent.contains("Application started successfully")) {

456

// Check if SSL is enabled

457

boolean sslEnabled = logContent.contains("HTTPS server started");

458

return new StartedResult(sslEnabled);

459

}

460

461

// Check for startup failure

462

if (logContent.contains("Application failed to start")) {

463

throw new RuntimeException("Application startup failed");

464

}

465

466

// Not started yet

467

return Result.NotStarted.INSTANCE;

468

469

} catch (IOException e) {

470

// Log file not readable yet

471

return Result.NotStarted.INSTANCE;

472

}

473

}

474

475

private static class StartedResult implements Result {

476

private final boolean ssl;

477

478

public StartedResult(boolean ssl) {

479

this.ssl = ssl;

480

}

481

482

@Override

483

public boolean isStarted() {

484

return true;

485

}

486

487

@Override

488

public boolean isSsl() {

489

return ssl;

490

}

491

}

492

}

493

```

494

495

**Service Registration:**

496

497

Create `META-INF/services/io.quarkus.test.common.IntegrationTestStartedNotifier`:

498

499

```

500

com.mycompany.test.CustomStartupNotifier

501

```

502

503

**Legacy Native Image Notifier (Deprecated):**

504

505

```java

506

@Deprecated

507

public class LegacyNativeNotifier implements NativeImageStartedNotifier {

508

@Override

509

public boolean isNativeImageStarted() {

510

// Legacy implementation - use IntegrationTestStartedNotifier instead

511

return checkApplicationProcess();

512

}

513

514

private boolean checkApplicationProcess() {

515

// Implementation to check if native process is running

516

return true;

517

}

518

}

519

```