or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdcontainers.mdexternal-systems.mdindex.mdjunit-integration.mdmetrics.mdtest-environments.mdtest-suites.md

junit-integration.mddocs/

0

# JUnit Integration

1

2

The JUnit integration provides annotation-driven configuration with automatic resource lifecycle management and test parameterization. It extends JUnit 5 with specialized extensions for connector testing.

3

4

## Capabilities

5

6

### Core Annotations

7

8

Annotations for marking test resources and configuration in test classes.

9

10

```java { .api }

11

/**

12

* Marks field defining TestEnvironment (PER-CLASS lifecycle)

13

* Only one field per test class can be annotated with @TestEnv

14

*/

15

@Target(ElementType.FIELD)

16

@Retention(RetentionPolicy.RUNTIME)

17

public @interface TestEnv {}

18

19

/**

20

* Marks field defining ExternalContextFactory (PER-CASE lifecycle)

21

* Multiple fields can be annotated for different external systems

22

*/

23

@Target(ElementType.FIELD)

24

@Retention(RetentionPolicy.RUNTIME)

25

public @interface TestContext {}

26

27

/**

28

* Marks field defining external system configuration

29

*/

30

@Target(ElementType.FIELD)

31

@Retention(RetentionPolicy.RUNTIME)

32

public @interface TestExternalSystem {}

33

34

/**

35

* Marks field defining semantic guarantees for testing

36

*/

37

@Target(ElementType.FIELD)

38

@Retention(RetentionPolicy.RUNTIME)

39

public @interface TestSemantics {}

40

```

41

42

**Usage Examples:**

43

44

```java

45

import org.apache.flink.connector.testframe.junit.annotations.*;

46

import org.apache.flink.connector.testframe.junit.extensions.ConnectorTestingExtension;

47

48

@ExtendWith(ConnectorTestingExtension.class)

49

public class MyConnectorTestSuite extends SinkTestSuiteBase<String> {

50

51

// Test environment (PER-CLASS lifecycle)

52

@TestEnv

53

MiniClusterTestEnvironment testEnv = new MiniClusterTestEnvironment();

54

55

// External context factory (PER-CASE lifecycle)

56

@TestContext

57

ExternalContextFactory<MySinkExternalContext> sinkContextFactory =

58

testName -> new MySinkExternalContext(testName);

59

60

// Multiple contexts supported

61

@TestContext

62

ExternalContextFactory<MyOtherExternalContext> otherContextFactory =

63

testName -> new MyOtherExternalContext(testName);

64

65

// External system configuration

66

@TestExternalSystem

67

MyExternalSystemConfig externalConfig = new MyExternalSystemConfig();

68

69

// Semantic configuration

70

@TestSemantics

71

List<CheckpointingMode> semantics = Arrays.asList(

72

CheckpointingMode.EXACTLY_ONCE,

73

CheckpointingMode.AT_LEAST_ONCE

74

);

75

}

76

```

77

78

### Connector Testing Extension

79

80

Main JUnit 5 extension that orchestrates the testing framework.

81

82

```java { .api }

83

/**

84

* Main JUnit 5 extension for connector testing framework

85

* Provides automatic lifecycle management and parameter injection

86

*/

87

public class ConnectorTestingExtension implements

88

BeforeAllCallback, // Initialize PER-CLASS resources

89

AfterAllCallback, // Cleanup PER-CLASS resources

90

TestTemplateInvocationContextProvider, // Provide test parameterization

91

ParameterResolver // Inject parameters into test methods

92

{

93

94

/**

95

* Initialize test environment and PER-CLASS resources

96

* Called once before all test methods in the class

97

*/

98

@Override

99

public void beforeAll(ExtensionContext context) throws Exception;

100

101

/**

102

* Cleanup test environment and PER-CLASS resources

103

* Called once after all test methods in the class

104

*/

105

@Override

106

public void afterAll(ExtensionContext context) throws Exception;

107

108

/**

109

* Provide test invocation contexts for parameterized testing

110

* Generates combinations of external contexts and semantic modes

111

*/

112

@Override

113

public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context);

114

115

/**

116

* Resolve parameters for test method injection

117

* Supports TestEnvironment, ExternalContext, CheckpointingMode, ClusterControllable

118

*/

119

@Override

120

public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext);

121

122

@Override

123

public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext);

124

}

125

```

126

127

**Automatic Features:**

128

129

- **Resource Lifecycle**: Automatic startup/teardown of test environments

130

- **Parameter Injection**: Injects test resources into `@TestTemplate` methods

131

- **Test Parameterization**: Generates test combinations across contexts and semantics

132

- **Error Handling**: Proper cleanup even when tests fail

133

- **Parallel Execution**: Supports parallel test execution with resource isolation

134

135

### Test Case Invocation Context Provider

136

137

Provides context for individual test case invocations with proper parameter resolution.

138

139

```java { .api }

140

/**

141

* Provides test case invocation contexts with parameter resolution

142

*/

143

public class TestCaseInvocationContextProvider implements TestTemplateInvocationContextProvider {

144

145

/**

146

* Check if extension supports the test method

147

* @param context Extension context

148

* @return true if method uses @TestTemplate with supported parameters

149

*/

150

@Override

151

public boolean supportsTestTemplate(ExtensionContext context);

152

153

/**

154

* Provide invocation contexts for test template

155

* @param context Extension context

156

* @return Stream of invocation contexts for parameter combinations

157

*/

158

@Override

159

public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context);

160

}

161

```

162

163

## Test Method Signatures

164

165

### Supported Parameter Types

166

167

Test methods can declare parameters that will be automatically injected:

168

169

```java { .api }

170

// Supported parameter types for @TestTemplate methods:

171

172

/**

173

* Test environment instance (PER-CLASS lifecycle)

174

*/

175

TestEnvironment testEnv

176

177

/**

178

* External context for sink testing (PER-CASE lifecycle)

179

*/

180

DataStreamSinkExternalContext<T> externalContext

181

182

/**

183

* External context for source testing (PER-CASE lifecycle)

184

*/

185

DataStreamSourceExternalContext<T> externalContext

186

187

/**

188

* Checkpointing semantic mode (injected per test variation)

189

*/

190

CheckpointingMode semantic

191

192

/**

193

* Cluster controller for failure testing (when supported by environment)

194

*/

195

ClusterControllable controller

196

```

197

198

**Example Method Signatures:**

199

200

```java

201

// Sink test method

202

@TestTemplate

203

public void testBasicSink(

204

TestEnvironment testEnv,

205

DataStreamSinkExternalContext<String> externalContext,

206

CheckpointingMode semantic

207

) throws Exception {

208

// Test implementation

209

}

210

211

// Source test method with failure testing

212

@TestTemplate

213

public void testTaskManagerFailure(

214

TestEnvironment testEnv,

215

DataStreamSourceExternalContext<String> externalContext,

216

ClusterControllable controller,

217

CheckpointingMode semantic

218

) throws Exception {

219

// Test implementation

220

}

221

222

// Custom test method

223

@TestTemplate

224

public void testCustomScenario(

225

TestEnvironment testEnv,

226

DataStreamSinkExternalContext<String> sinkContext,

227

DataStreamSourceExternalContext<String> sourceContext,

228

CheckpointingMode semantic

229

) throws Exception {

230

// Custom test with multiple contexts

231

}

232

```

233

234

## Lifecycle Management

235

236

### PER-CLASS Resources

237

238

Resources with PER-CLASS lifecycle are shared across all test methods in the class.

239

240

```java

241

@TestEnv

242

MiniClusterTestEnvironment testEnv = new MiniClusterTestEnvironment();

243

244

// Lifecycle:

245

// 1. Created when test class is instantiated

246

// 2. Started before first test method (@BeforeAll phase)

247

// 3. Shared by all test methods in the class

248

// 4. Stopped after last test method (@AfterAll phase)

249

```

250

251

**Benefits:**

252

- **Performance**: Avoids expensive cluster startup/teardown per test

253

- **Resource Efficiency**: Reduces memory and CPU usage

254

- **Test Speed**: Faster test execution

255

256

### PER-CASE Resources

257

258

Resources with PER-CASE lifecycle are created fresh for each test case.

259

260

```java

261

@TestContext

262

ExternalContextFactory<MySinkExternalContext> contextFactory =

263

testName -> new MySinkExternalContext(testName);

264

265

// Lifecycle:

266

// 1. Factory created when test class is instantiated

267

// 2. New context instance created before each test case

268

// 3. Context used during test execution

269

// 4. Context closed after test case completion

270

```

271

272

**Benefits:**

273

- **Test Isolation**: Each test gets fresh external resources

274

- **Resource Cleanup**: Automatic cleanup prevents resource leaks

275

- **Parallel Safety**: Tests can run in parallel safely

276

277

### Lifecycle Sequence

278

279

```java

280

// Class initialization

281

TestClass instance = new TestClass();

282

283

// Before all tests

284

@BeforeAll

285

testEnv.startUp(); // Start test environment

286

287

// For each test method

288

for (TestMethod method : testMethods) {

289

// For each parameter combination

290

for (ParameterCombination params : combinations) {

291

292

// Before each test case

293

ExternalContext context = contextFactory.createExternalContext(testName);

294

295

try {

296

// Execute test

297

method.invoke(testEnv, context, semantic);

298

} finally {

299

// After each test case

300

context.close(); // Cleanup external resources

301

}

302

}

303

}

304

305

// After all tests

306

@AfterAll

307

testEnv.tearDown(); // Stop test environment

308

```

309

310

## Test Parameterization

311

312

### Automatic Parameter Generation

313

314

The framework automatically generates test parameter combinations:

315

316

```java

317

// Configuration

318

@TestContext

319

ExternalContextFactory<Context1> context1Factory = ...;

320

321

@TestContext

322

ExternalContextFactory<Context2> context2Factory = ...;

323

324

@TestSemantics

325

List<CheckpointingMode> semantics = Arrays.asList(

326

CheckpointingMode.EXACTLY_ONCE,

327

CheckpointingMode.AT_LEAST_ONCE

328

);

329

330

// Generated combinations:

331

// 1. testMethod(testEnv, context1, EXACTLY_ONCE)

332

// 2. testMethod(testEnv, context1, AT_LEAST_ONCE)

333

// 3. testMethod(testEnv, context2, EXACTLY_ONCE)

334

// 4. testMethod(testEnv, context2, AT_LEAST_ONCE)

335

```

336

337

### Display Names

338

339

Test cases get descriptive display names based on parameters:

340

341

```java

342

// Generated display names:

343

// ✓ testBasicSink[Context1, EXACTLY_ONCE]

344

// ✓ testBasicSink[Context1, AT_LEAST_ONCE]

345

// ✓ testBasicSink[Context2, EXACTLY_ONCE]

346

// ✓ testBasicSink[Context2, AT_LEAST_ONCE]

347

```

348

349

### Custom Parameterization

350

351

Override default parameterization for specific test methods:

352

353

```java

354

@TestTemplate

355

@ParameterizedTest

356

@EnumSource(CheckpointingMode.class)

357

public void testCustomParameterization(

358

TestEnvironment testEnv,

359

DataStreamSinkExternalContext<String> externalContext,

360

CheckpointingMode semantic

361

) throws Exception {

362

// Custom parameterization using JUnit 5 @ParameterizedTest

363

}

364

```

365

366

## Advanced Configuration

367

368

### Multiple External Systems

369

370

Test with multiple external systems simultaneously:

371

372

```java

373

@TestContext

374

ExternalContextFactory<DatabaseExternalContext> dbContextFactory =

375

testName -> new DatabaseExternalContext(testName);

376

377

@TestContext

378

ExternalContextFactory<MessageQueueExternalContext> mqContextFactory =

379

testName -> new MessageQueueExternalContext(testName);

380

381

@TestTemplate

382

public void testDatabaseToMessageQueue(

383

TestEnvironment testEnv,

384

DatabaseExternalContext dbContext,

385

MessageQueueExternalContext mqContext,

386

CheckpointingMode semantic

387

) throws Exception {

388

// Test data flow from database to message queue

389

}

390

```

391

392

### Conditional Test Execution

393

394

Skip tests based on environment or configuration:

395

396

```java

397

@TestTemplate

398

public void testContainerizedEnvironment(

399

TestEnvironment testEnv,

400

DataStreamSinkExternalContext<String> externalContext,

401

CheckpointingMode semantic

402

) throws Exception {

403

404

assumeTrue(testEnv instanceof FlinkContainerTestEnvironment,

405

"Test requires containerized environment");

406

407

// Test implementation

408

}

409

410

@TestTemplate

411

public void testExactlyOnceOnly(

412

TestEnvironment testEnv,

413

DataStreamSinkExternalContext<String> externalContext,

414

CheckpointingMode semantic

415

) throws Exception {

416

417

assumeTrue(semantic == CheckpointingMode.EXACTLY_ONCE,

418

"Test only valid for exactly-once semantic");

419

420

// Test implementation

421

}

422

```

423

424

### Error Handling Configuration

425

426

Configure error handling behavior:

427

428

```java

429

@ExtendWith(ConnectorTestingExtension.class)

430

@TestMethodOrder(OrderAnnotation.class)

431

public class MyConnectorTestSuite extends SinkTestSuiteBase<String> {

432

433

@TestEnv

434

MiniClusterTestEnvironment testEnv = new MiniClusterTestEnvironment();

435

436

@TestContext

437

ExternalContextFactory<MySinkExternalContext> contextFactory = testName -> {

438

try {

439

return new MySinkExternalContext(testName);

440

} catch (Exception e) {

441

// Convert to TestAbortedException to skip test instead of failing

442

throw new TestAbortedException("External system not available", e);

443

}

444

};

445

446

@Order(1)

447

@TestTemplate

448

public void testPrerequisites(TestEnvironment testEnv) {

449

// Verify prerequisites before running main tests

450

assumeTrue(checkExternalSystemAvailability(),

451

"External system not available");

452

}

453

}

454

```

455

456

## Integration with IDEs

457

458

### IntelliJ IDEA

459

460

- **Test Discovery**: Automatically discovers `@TestTemplate` methods

461

- **Parameter Display**: Shows parameter combinations in test tree

462

- **Debug Support**: Full debugging support with parameter inspection

463

- **Test Filtering**: Filter tests by parameter values

464

465

### Eclipse

466

467

- **JUnit 5 Support**: Requires JUnit 5 plugin for full support

468

- **Test Execution**: Run individual parameter combinations

469

- **Progress Reporting**: Shows progress across parameter combinations

470

471

### Maven/Gradle

472

473

```xml

474

<!-- Maven Surefire configuration -->

475

<plugin>

476

<groupId>org.apache.maven.plugins</groupId>

477

<artifactId>maven-surefire-plugin</artifactId>

478

<version>3.0.0-M9</version>

479

<configuration>

480

<includes>

481

<include>**/*TestSuite.java</include>

482

</includes>

483

<!-- Enable parallel execution -->

484

<parallel>methods</parallel>

485

<threadCount>4</threadCount>

486

</configuration>

487

</plugin>

488

```

489

490

```gradle

491

// Gradle test configuration

492

test {

493

useJUnitPlatform()

494

495

// Enable parallel execution

496

maxParallelForks = 4

497

498

// Configure test logging

499

testLogging {

500

events "passed", "skipped", "failed"

501

showStandardStreams = true

502

}

503

}

504

```