or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdconditional-execution.mdcore-testing.mddynamic-tests.mdextensions.mdindex.mdparallel-execution.mdparameterized-tests.md

parameterized-tests.mddocs/

0

# Parameterized Tests

1

2

Advanced parameterized testing capabilities that allow running the same test logic with different sets of arguments. JUnit Jupiter provides multiple ways to supply test arguments with support for custom conversion and aggregation.

3

4

## Imports

5

6

```java

7

import org.junit.jupiter.params.ParameterizedTest;

8

import org.junit.jupiter.params.provider.*;

9

import org.junit.jupiter.params.aggregator.*;

10

import org.junit.jupiter.params.converter.*;

11

import static org.junit.jupiter.api.Assertions.*;

12

```

13

14

## Capabilities

15

16

### Parameterized Test Annotation

17

18

Core annotation for defining parameterized tests.

19

20

```java { .api }

21

/**

22

* Marks a method as a parameterized test with multiple argument sources

23

*/

24

@Target(ElementType.METHOD)

25

@Retention(RetentionPolicy.RUNTIME)

26

@interface ParameterizedTest {

27

/**

28

* Custom name pattern for parameterized test invocations

29

*/

30

String name() default "[{index}] {arguments}";

31

32

/**

33

* How to handle argument count mismatches

34

*/

35

ArgumentCountValidationMode argumentCountValidationMode() default ArgumentCountValidationMode.STRICT;

36

}

37

38

enum ArgumentCountValidationMode {

39

STRICT, // Fail if parameter count doesn't match

40

LENIENT, // Allow missing parameters (null values)

41

IGNORE // Ignore extra arguments

42

}

43

```

44

45

**Basic Usage:**

46

47

```java

48

@ParameterizedTest

49

@ValueSource(ints = {1, 2, 3})

50

void testWithValueSource(int argument) {

51

assertTrue(argument > 0);

52

}

53

54

@ParameterizedTest(name = "Run {index}: testing with value {0}")

55

@ValueSource(strings = {"apple", "banana", "cherry"})

56

void testWithCustomName(String fruit) {

57

assertNotNull(fruit);

58

assertTrue(fruit.length() > 3);

59

}

60

```

61

62

### Value Sources

63

64

Simple argument sources for primitive types and strings.

65

66

```java { .api }

67

/**

68

* Array of literal values as arguments

69

*/

70

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

71

@Retention(RetentionPolicy.RUNTIME)

72

@ArgumentsSource(ValueArgumentsProvider.class)

73

@interface ValueSource {

74

short[] shorts() default {};

75

byte[] bytes() default {};

76

int[] ints() default {};

77

long[] longs() default {};

78

float[] floats() default {};

79

double[] doubles() default {};

80

char[] chars() default {};

81

boolean[] booleans() default {};

82

String[] strings() default {};

83

Class<?>[] classes() default {};

84

}

85

86

/**

87

* Container for multiple value sources

88

*/

89

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

90

@Retention(RetentionPolicy.RUNTIME)

91

@interface ValueSources {

92

ValueSource[] value();

93

}

94

```

95

96

**Usage Examples:**

97

98

```java

99

@ParameterizedTest

100

@ValueSource(ints = {1, 2, 3, 4, 5})

101

void testNumbers(int number) {

102

assertTrue(number > 0 && number < 6);

103

}

104

105

@ParameterizedTest

106

@ValueSource(strings = {"", " "})

107

void testBlankStrings(String input) {

108

assertTrue(input.isBlank());

109

}

110

111

@ParameterizedTest

112

@ValueSource(booleans = {true, false})

113

void testBooleans(boolean value) {

114

// Test both true and false cases

115

assertNotNull(Boolean.valueOf(value));

116

}

117

118

@ParameterizedTest

119

@ValueSource(classes = {String.class, Integer.class, List.class})

120

void testClasses(Class<?> clazz) {

121

assertNotNull(clazz);

122

assertNotNull(clazz.getName());

123

}

124

```

125

126

### Null and Empty Sources

127

128

Special argument sources for null and empty values.

129

130

```java { .api }

131

/**

132

* Provides a single null argument

133

*/

134

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

135

@Retention(RetentionPolicy.RUNTIME)

136

@ArgumentsSource(NullArgumentsProvider.class)

137

@interface NullSource {

138

}

139

140

/**

141

* Provides empty values for strings, lists, sets, maps, and primitive arrays

142

*/

143

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

144

@Retention(RetentionPolicy.RUNTIME)

145

@ArgumentsSource(EmptyArgumentsProvider.class)

146

@interface EmptySource {

147

}

148

149

/**

150

* Combines null and empty sources

151

*/

152

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

153

@Retention(RetentionPolicy.RUNTIME)

154

@NullSource

155

@EmptySource

156

@interface NullAndEmptySource {

157

}

158

```

159

160

**Usage Examples:**

161

162

```java

163

@ParameterizedTest

164

@NullSource

165

@ValueSource(strings = {"", " ", "valid"})

166

void testStringValidation(String input) {

167

// Test with null, empty, blank, and valid strings

168

String result = StringUtils.clean(input);

169

// Assert based on input type

170

}

171

172

@ParameterizedTest

173

@NullAndEmptySource

174

@ValueSource(strings = {"apple", "banana"})

175

void testStringProcessing(String input) {

176

// Test null, empty, and actual values

177

String processed = processString(input);

178

if (input == null || input.isEmpty()) {

179

assertEquals("default", processed);

180

} else {

181

assertNotEquals("default", processed);

182

}

183

}

184

185

@ParameterizedTest

186

@EmptySource

187

@ValueSource(ints = {1, 2, 3})

188

void testIntArrays(int[] array) {

189

// Test with empty array and arrays with values

190

assertNotNull(array);

191

}

192

```

193

194

### Enum Sources

195

196

Arguments from enum values with filtering options.

197

198

```java { .api }

199

/**

200

* Provides enum values as arguments

201

*/

202

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

203

@Retention(RetentionPolicy.RUNTIME)

204

@ArgumentsSource(EnumArgumentsProvider.class)

205

@interface EnumSource {

206

/**

207

* Enum class to get values from

208

*/

209

Class<? extends Enum<?>> value();

210

211

/**

212

* Enum constant names to include/exclude

213

*/

214

String[] names() default {};

215

216

/**

217

* Whether to include or exclude specified names

218

*/

219

Mode mode() default Mode.INCLUDE;

220

221

enum Mode {

222

INCLUDE, // Include only specified names

223

EXCLUDE, // Exclude specified names

224

MATCH_ALL, // Include names matching all patterns

225

MATCH_ANY // Include names matching any pattern

226

}

227

}

228

229

/**

230

* Container for multiple enum sources

231

*/

232

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

233

@Retention(RetentionPolicy.RUNTIME)

234

@interface EnumSources {

235

EnumSource[] value();

236

}

237

```

238

239

**Usage Examples:**

240

241

```java

242

enum Color {

243

RED, GREEN, BLUE, YELLOW, PURPLE

244

}

245

246

@ParameterizedTest

247

@EnumSource(Color.class)

248

void testAllColors(Color color) {

249

assertNotNull(color);

250

assertTrue(color.name().length() > 2);

251

}

252

253

@ParameterizedTest

254

@EnumSource(value = Color.class, names = {"RED", "BLUE"})

255

void testSpecificColors(Color color) {

256

assertTrue(color == Color.RED || color == Color.BLUE);

257

}

258

259

@ParameterizedTest

260

@EnumSource(value = Color.class, names = {"YELLOW"}, mode = EnumSource.Mode.EXCLUDE)

261

void testAllColorsExceptYellow(Color color) {

262

assertNotEquals(Color.YELLOW, color);

263

}

264

265

@ParameterizedTest

266

@EnumSource(value = Color.class, names = {"^B.*"}, mode = EnumSource.Mode.MATCH_ALL)

267

void testColorsStartingWithB(Color color) {

268

assertTrue(color.name().startsWith("B"));

269

}

270

```

271

272

### CSV Sources

273

274

Arguments from CSV data, either inline or from files.

275

276

```java { .api }

277

/**

278

* Provides CSV data as arguments

279

*/

280

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

281

@Retention(RetentionPolicy.RUNTIME)

282

@ArgumentsSource(CsvArgumentsProvider.class)

283

@interface CsvSource {

284

/**

285

* CSV records as string array

286

*/

287

String[] value();

288

289

/**

290

* Column delimiter character

291

*/

292

char delimiter() default ',';

293

294

/**

295

* String to represent null values

296

*/

297

String nullValues() default "";

298

299

/**

300

* Quote character for escaping

301

*/

302

char quoteCharacter() default '"';

303

304

/**

305

* How to handle empty values

306

*/

307

EmptyValue emptyValue() default EmptyValue.EMPTY_STRING;

308

309

/**

310

* Whether to ignore leading/trailing whitespace

311

*/

312

boolean ignoreLeadingAndTrailingWhitespace() default true;

313

314

enum EmptyValue {

315

EMPTY_STRING, // Empty string ""

316

NULL_REFERENCE // null

317

}

318

}

319

320

/**

321

* Container for multiple CSV sources

322

*/

323

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

324

@Retention(RetentionPolicy.RUNTIME)

325

@interface CsvSources {

326

CsvSource[] value();

327

}

328

```

329

330

**Usage Examples:**

331

332

```java

333

@ParameterizedTest

334

@CsvSource({

335

"apple, 1",

336

"banana, 2",

337

"'lemon, lime', 3"

338

})

339

void testWithCsvSource(String fruit, int rank) {

340

assertNotNull(fruit);

341

assertTrue(rank > 0);

342

}

343

344

@ParameterizedTest

345

@CsvSource(value = {

346

"John:25:Engineer",

347

"Jane:30:Manager",

348

"Bob:35:Developer"

349

}, delimiter = ':')

350

void testPersonData(String name, int age, String role) {

351

assertNotNull(name);

352

assertTrue(age > 0);

353

assertNotNull(role);

354

}

355

356

@ParameterizedTest

357

@CsvSource(value = {

358

"test, NULL, 42",

359

"example, , 0"

360

}, nullValues = "NULL")

361

void testWithNullValues(String str, String nullableStr, int number) {

362

assertNotNull(str);

363

// nullableStr might be null

364

assertTrue(number >= 0);

365

}

366

```

367

368

### CSV File Sources

369

370

Arguments from external CSV files.

371

372

```java { .api }

373

/**

374

* Provides CSV data from files as arguments

375

*/

376

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

377

@Retention(RetentionPolicy.RUNTIME)

378

@ArgumentsSource(CsvFileArgumentsProvider.class)

379

@interface CsvFileSource {

380

/**

381

* CSV file resources (classpath relative)

382

*/

383

String[] resources() default {};

384

385

/**

386

* CSV files (file system paths)

387

*/

388

String[] files() default {};

389

390

/**

391

* Character encoding for files

392

*/

393

String encoding() default "UTF-8";

394

395

/**

396

* Line separator for files

397

*/

398

String lineSeparator() default "\n";

399

400

/**

401

* Column delimiter character

402

*/

403

char delimiter() default ',';

404

405

/**

406

* String to represent null values

407

*/

408

String nullValues() default "";

409

410

/**

411

* Quote character for escaping

412

*/

413

char quoteCharacter() default '"';

414

415

/**

416

* How to handle empty values

417

*/

418

CsvSource.EmptyValue emptyValue() default CsvSource.EmptyValue.EMPTY_STRING;

419

420

/**

421

* Whether to ignore leading/trailing whitespace

422

*/

423

boolean ignoreLeadingAndTrailingWhitespace() default true;

424

425

/**

426

* Number of header lines to skip

427

*/

428

int numLinesToSkip() default 0;

429

}

430

431

/**

432

* Container for multiple CSV file sources

433

*/

434

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

435

@Retention(RetentionPolicy.RUNTIME)

436

@interface CsvFileSources {

437

CsvFileSource[] value();

438

}

439

```

440

441

**Usage Examples:**

442

443

```java

444

@ParameterizedTest

445

@CsvFileSource(resources = "/test-data.csv", numLinesToSkip = 1)

446

void testWithCsvFileSource(String name, int age, String city) {

447

assertNotNull(name);

448

assertTrue(age > 0);

449

assertNotNull(city);

450

}

451

452

@ParameterizedTest

453

@CsvFileSource(files = "src/test/resources/users.csv", delimiter = ';')

454

void testUserData(String username, String email, boolean active) {

455

assertNotNull(username);

456

assertTrue(email.contains("@"));

457

// active can be true or false

458

}

459

```

460

461

### Method Sources

462

463

Arguments from static methods.

464

465

```java { .api }

466

/**

467

* Provides arguments from static methods

468

*/

469

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

470

@Retention(RetentionPolicy.RUNTIME)

471

@ArgumentsSource(MethodArgumentsProvider.class)

472

@interface MethodSource {

473

/**

474

* Method names that provide arguments

475

* If empty, uses test method name

476

*/

477

String[] value() default {};

478

}

479

480

/**

481

* Container for multiple method sources

482

*/

483

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

484

@Retention(RetentionPolicy.RUNTIME)

485

@interface MethodSources {

486

MethodSource[] value();

487

}

488

```

489

490

**Usage Examples:**

491

492

```java

493

@ParameterizedTest

494

@MethodSource("stringProvider")

495

void testWithMethodSource(String argument) {

496

assertNotNull(argument);

497

}

498

499

static Stream<String> stringProvider() {

500

return Stream.of("apple", "banana", "cherry");

501

}

502

503

@ParameterizedTest

504

@MethodSource("personProvider")

505

void testPersons(Person person) {

506

assertNotNull(person.getName());

507

assertTrue(person.getAge() > 0);

508

}

509

510

static Stream<Person> personProvider() {

511

return Stream.of(

512

new Person("John", 25),

513

new Person("Jane", 30),

514

new Person("Bob", 35)

515

);

516

}

517

518

@ParameterizedTest

519

@MethodSource("argumentProvider")

520

void testWithMultipleArguments(int number, String text, boolean flag) {

521

assertTrue(number > 0);

522

assertNotNull(text);

523

// flag can be any boolean value

524

}

525

526

static Stream<Arguments> argumentProvider() {

527

return Stream.of(

528

Arguments.of(1, "first", true),

529

Arguments.of(2, "second", false),

530

Arguments.of(3, "third", true)

531

);

532

}

533

```

534

535

### Field Sources

536

537

Arguments from static fields.

538

539

```java { .api }

540

/**

541

* Provides arguments from static fields

542

*/

543

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

544

@Retention(RetentionPolicy.RUNTIME)

545

@ArgumentsSource(FieldArgumentsProvider.class)

546

@interface FieldSource {

547

/**

548

* Field names that provide arguments

549

* If empty, uses test method name

550

*/

551

String[] value() default {};

552

}

553

554

/**

555

* Container for multiple field sources

556

*/

557

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

558

@Retention(RetentionPolicy.RUNTIME)

559

@interface FieldSources {

560

FieldSource[] value();

561

}

562

```

563

564

**Usage Examples:**

565

566

```java

567

static List<String> fruits = Arrays.asList("apple", "banana", "cherry");

568

569

@ParameterizedTest

570

@FieldSource("fruits")

571

void testWithFieldSource(String fruit) {

572

assertNotNull(fruit);

573

assertTrue(fruit.length() > 3);

574

}

575

576

static Stream<Arguments> testData = Stream.of(

577

Arguments.of(1, "one"),

578

Arguments.of(2, "two"),

579

Arguments.of(3, "three")

580

);

581

582

@ParameterizedTest

583

@FieldSource("testData")

584

void testWithArgumentsField(int number, String word) {

585

assertTrue(number > 0);

586

assertNotNull(word);

587

}

588

```

589

590

### Custom Argument Sources

591

592

Create custom argument providers for complex scenarios.

593

594

```java { .api }

595

/**

596

* Custom arguments source annotation

597

*/

598

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

599

@Retention(RetentionPolicy.RUNTIME)

600

@ArgumentsSource(CustomArgumentsProvider.class)

601

@interface ArgumentsSource {

602

/**

603

* ArgumentsProvider implementation class

604

*/

605

Class<? extends ArgumentsProvider> value();

606

}

607

608

/**

609

* Container for multiple custom sources

610

*/

611

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})

612

@Retention(RetentionPolicy.RUNTIME)

613

@interface ArgumentsSources {

614

ArgumentsSource[] value();

615

}

616

617

/**

618

* Arguments provider interface

619

*/

620

interface ArgumentsProvider {

621

/**

622

* Provide arguments for parameterized test

623

*/

624

Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception;

625

}

626

627

/**

628

* Base class for annotation-based providers

629

*/

630

abstract class AnnotationBasedArgumentsProvider<T extends Annotation> implements ArgumentsProvider {

631

/**

632

* Accept annotation for configuration

633

*/

634

protected abstract void accept(T annotation);

635

}

636

```

637

638

**Usage Example:**

639

640

```java

641

@Target(ElementType.METHOD)

642

@Retention(RetentionPolicy.RUNTIME)

643

@ArgumentsSource(RandomIntegerProvider.class)

644

@interface RandomIntegers {

645

int count() default 10;

646

int min() default 0;

647

int max() default 100;

648

}

649

650

class RandomIntegerProvider extends AnnotationBasedArgumentsProvider<RandomIntegers> {

651

private int count;

652

private int min;

653

private int max;

654

655

@Override

656

protected void accept(RandomIntegers annotation) {

657

this.count = annotation.count();

658

this.min = annotation.min();

659

this.max = annotation.max();

660

}

661

662

@Override

663

public Stream<Arguments> provideArguments(ExtensionContext context) {

664

Random random = new Random();

665

return random.ints(count, min, max)

666

.mapToObj(Arguments::of);

667

}

668

}

669

670

@ParameterizedTest

671

@RandomIntegers(count = 5, min = 1, max = 10)

672

void testWithRandomIntegers(int value) {

673

assertTrue(value >= 1 && value <= 10);

674

}

675

```

676

677

### Argument Conversion

678

679

Convert string arguments to other types automatically or with custom converters.

680

681

```java { .api }

682

/**

683

* Custom argument converter annotation

684

*/

685

@Target({ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})

686

@Retention(RetentionPolicy.RUNTIME)

687

@interface ConvertWith {

688

/**

689

* ArgumentConverter implementation class

690

*/

691

Class<? extends ArgumentConverter> value();

692

}

693

694

/**

695

* Java time conversion pattern

696

*/

697

@Target({ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})

698

@Retention(RetentionPolicy.RUNTIME)

699

@ConvertWith(JavaTimeArgumentConverter.class)

700

@interface JavaTimeConversionPattern {

701

/**

702

* Pattern for parsing date/time

703

*/

704

String value();

705

}

706

707

/**

708

* Argument converter interface

709

*/

710

interface ArgumentConverter<S, T> {

711

/**

712

* Convert source argument to target type

713

*/

714

T convert(S source, ParameterContext context) throws ArgumentConversionException;

715

}

716

717

/**

718

* Simple converter for single argument types

719

*/

720

abstract class SimpleArgumentConverter<S, T> implements ArgumentConverter<S, T> {

721

@Override

722

public final T convert(S source, ParameterContext context) throws ArgumentConversionException {

723

return convert(source, context.getParameter().getType());

724

}

725

726

/**

727

* Convert source to target type

728

*/

729

protected abstract T convert(S source, Class<?> targetType) throws ArgumentConversionException;

730

}

731

732

/**

733

* Typed converter with type safety

734

*/

735

abstract class TypedArgumentConverter<S, T> extends SimpleArgumentConverter<S, T> {

736

private final Class<S> sourceType;

737

private final Class<T> targetType;

738

739

protected TypedArgumentConverter(Class<S> sourceType, Class<T> targetType) {

740

this.sourceType = sourceType;

741

this.targetType = targetType;

742

}

743

}

744

```

745

746

**Usage Examples:**

747

748

```java

749

@ParameterizedTest

750

@ValueSource(strings = {"2023-01-01", "2023-12-31"})

751

void testDates(@JavaTimeConversionPattern("yyyy-MM-dd") LocalDate date) {

752

assertNotNull(date);

753

assertEquals(2023, date.getYear());

754

}

755

756

class StringToPersonConverter extends TypedArgumentConverter<String, Person> {

757

protected StringToPersonConverter() {

758

super(String.class, Person.class);

759

}

760

761

@Override

762

protected Person convert(String source, Class<?> targetType) {

763

String[] parts = source.split(",");

764

return new Person(parts[0], Integer.parseInt(parts[1]));

765

}

766

}

767

768

@ParameterizedTest

769

@ValueSource(strings = {"John,25", "Jane,30", "Bob,35"})

770

void testPersonConversion(@ConvertWith(StringToPersonConverter.class) Person person) {

771

assertNotNull(person.getName());

772

assertTrue(person.getAge() > 0);

773

}

774

```

775

776

### Argument Aggregation

777

778

Aggregate multiple arguments into complex objects.

779

780

```java { .api }

781

/**

782

* Custom argument aggregator annotation

783

*/

784

@Target(ElementType.PARAMETER)

785

@Retention(RetentionPolicy.RUNTIME)

786

@interface AggregateWith {

787

/**

788

* ArgumentsAggregator implementation class

789

*/

790

Class<? extends ArgumentsAggregator> value();

791

}

792

793

/**

794

* Arguments aggregator interface

795

*/

796

interface ArgumentsAggregator {

797

/**

798

* Aggregate arguments into single object

799

*/

800

Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)

801

throws ArgumentsAggregationException;

802

}

803

804

/**

805

* Arguments accessor for retrieving individual arguments

806

*/

807

interface ArgumentsAccessor {

808

Object get(int index);

809

<T> T get(int index, Class<T> requiredType);

810

Character getCharacter(int index);

811

Boolean getBoolean(int index);

812

Byte getByte(int index);

813

Short getShort(int index);

814

Integer getInteger(int index);

815

Long getLong(int index);

816

Float getFloat(int index);

817

Double getDouble(int index);

818

String getString(int index);

819

int size();

820

Object[] toArray();

821

List<Object> toList();

822

}

823

```

824

825

**Usage Examples:**

826

827

```java

828

class PersonAggregator implements ArgumentsAggregator {

829

@Override

830

public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) {

831

return new Person(accessor.getString(0), accessor.getInteger(1));

832

}

833

}

834

835

@ParameterizedTest

836

@CsvSource({

837

"John, 25",

838

"Jane, 30",

839

"Bob, 35"

840

})

841

void testPersonAggregation(@AggregateWith(PersonAggregator.class) Person person) {

842

assertNotNull(person.getName());

843

assertTrue(person.getAge() > 0);

844

}

845

846

@ParameterizedTest

847

@CsvSource({

848

"John, 25, Engineer",

849

"Jane, 30, Manager",

850

"Bob, 35, Developer"

851

})

852

void testWithArgumentsAccessor(ArgumentsAccessor arguments) {

853

String name = arguments.getString(0);

854

int age = arguments.getInteger(1);

855

String role = arguments.getString(2);

856

857

Person person = new Person(name, age, role);

858

assertNotNull(person);

859

}

860

```

861

862

### Arguments Utility

863

864

Utility class for creating argument sets programmatically.

865

866

```java { .api }

867

/**

868

* Factory for creating Arguments instances

869

*/

870

interface Arguments {

871

/**

872

* Create Arguments from array of objects

873

*/

874

static Arguments of(Object... arguments);

875

876

/**

877

* Get arguments as object array

878

*/

879

Object[] get();

880

}

881

```

882

883

**Usage Example:**

884

885

```java

886

static Stream<Arguments> complexArgumentProvider() {

887

return Stream.of(

888

Arguments.of(1, "apple", true, new Person("John", 25)),

889

Arguments.of(2, "banana", false, new Person("Jane", 30)),

890

Arguments.of(3, "cherry", true, new Person("Bob", 35))

891

);

892

}

893

894

@ParameterizedTest

895

@MethodSource("complexArgumentProvider")

896

void testComplexArguments(int id, String fruit, boolean active, Person person) {

897

assertTrue(id > 0);

898

assertNotNull(fruit);

899

assertNotNull(person);

900

}

901

```