or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdassertions.mdassumptions.mdcategories.mdindex.mdmatchers.mdrules.mdstandard-runners.mdtest-runners.mdtheories.md

matchers.mddocs/

0

# Matchers

1

2

JUnit 4 integrates with Hamcrest matchers to provide expressive, readable assertions. Matchers allow you to write assertions in a more natural, English-like syntax and provide better error messages when assertions fail.

3

4

## Capabilities

5

6

### Matcher Assertions

7

8

Use Hamcrest matchers with JUnit assertions for expressive test verification.

9

10

**Note:** As of JUnit 4.13, the `assertThat` methods in `org.junit.Assert` are deprecated. Users should migrate to using Hamcrest's `MatcherAssert.assertThat()` directly, or use third-party assertion libraries like AssertJ or Google Truth.

11

12

**Import Consideration:** When using Hamcrest matchers, avoid using both `import static org.hamcrest.CoreMatchers.*` and `import static org.hamcrest.Matchers.*` together, as many methods exist in both classes and will cause ambiguous reference errors. Use only one wildcard import (typically `org.hamcrest.Matchers.*` which includes all matchers).

13

14

```java { .api }

15

/**

16

* Assert using Hamcrest matcher

17

* @param actual - Value to test

18

* @param matcher - Hamcrest matcher

19

* @deprecated Use {@link org.hamcrest.MatcherAssert#assertThat(Object, Matcher)} instead

20

*/

21

@Deprecated

22

public static <T> void assertThat(T actual, Matcher<? super T> matcher);

23

24

/**

25

* Assert using Hamcrest matcher with custom message

26

* @param reason - Message to display on failure

27

* @param actual - Value to test

28

* @param matcher - Hamcrest matcher

29

* @deprecated Use {@link org.hamcrest.MatcherAssert#assertThat(String, Object, Matcher)} instead

30

*/

31

@Deprecated

32

public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher);

33

```

34

35

**Usage Examples:**

36

37

```java

38

import org.junit.Test;

39

import static org.junit.Assert.assertThat;

40

import static org.hamcrest.CoreMatchers.*;

41

42

public class MatcherTest {

43

@Test

44

public void testWithMatchers() {

45

// Equality

46

assertThat(5, is(5));

47

assertThat("hello", equalTo("hello"));

48

49

// Negation

50

assertThat(5, not(3));

51

assertThat("hello", not("world"));

52

53

// Null checks

54

assertThat(null, nullValue());

55

assertThat("text", notNullValue());

56

57

// Type checks

58

assertThat("text", instanceOf(String.class));

59

assertThat(123, isA(Integer.class));

60

61

// String matchers

62

assertThat("hello world", containsString("world"));

63

assertThat("hello", startsWith("hel"));

64

assertThat("hello", endsWith("lo"));

65

66

// With custom message

67

assertThat("Value should be positive", 5, greaterThan(0));

68

}

69

70

@Test

71

public void testLogicalMatchers() {

72

// Any of (OR)

73

assertThat(5, either(is(5)).or(is(6)));

74

assertThat("test", anyOf(is("test"), is("demo"), is("example")));

75

76

// Both (AND)

77

assertThat(5, both(greaterThan(0)).and(lessThan(10)));

78

assertThat("test", allOf(startsWith("te"), endsWith("st")));

79

80

// Not

81

assertThat(5, not(lessThan(0)));

82

}

83

84

@Test

85

public void testCollectionMatchers() {

86

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

87

88

// Has item

89

assertThat(items, hasItem("banana"));

90

assertThat(items, hasItems("apple", "cherry"));

91

92

// Collection properties

93

assertThat(items, not(empty()));

94

assertThat(items.size(), is(3));

95

96

// Array matchers

97

String[] array = {"a", "b", "c"};

98

assertThat(array, arrayContaining("a", "b", "c"));

99

assertThat(array, arrayContainingInAnyOrder("b", "a", "c"));

100

}

101

}

102

```

103

104

### JUnitMatchers

105

106

JUnit-specific matcher utilities that extend Hamcrest matchers with additional functionality.

107

108

**Note:** Most methods in this class are deprecated. Use the equivalent methods from `org.hamcrest.CoreMatchers` instead. Only `isThrowable` and `isException` are not deprecated.

109

110

```java { .api }

111

/**

112

* JUnit-specific Hamcrest matchers

113

*/

114

public class JUnitMatchers {

115

/**

116

* Matcher for collection containing specific element

117

* @param element - Element to find

118

* @return Matcher that matches collections containing element

119

* @deprecated use {@link org.hamcrest.CoreMatchers#hasItem(Object)}

120

*/

121

@Deprecated

122

public static <T> Matcher<Iterable<? super T>> hasItem(T element);

123

124

/**

125

* Matcher for collection containing element matching the given matcher

126

* @param elementMatcher - Matcher for the element

127

* @return Matcher that matches collections containing matching element

128

* @deprecated use {@link org.hamcrest.CoreMatchers#hasItem(Matcher)}

129

*/

130

@Deprecated

131

public static <T> Matcher<Iterable<? super T>> hasItem(Matcher<? super T> elementMatcher);

132

133

/**

134

* Matcher for collection containing all specified elements

135

* @param elements - Elements to find

136

* @return Matcher that matches collections containing all elements

137

* @deprecated use {@link org.hamcrest.CoreMatchers#hasItems(Object...)}

138

*/

139

@Deprecated

140

public static <T> Matcher<Iterable<T>> hasItems(T... elements);

141

142

/**

143

* Matcher for collection containing elements matching all given matchers

144

* @param elementMatchers - Matchers for elements

145

* @return Matcher that matches collections with matching elements

146

* @deprecated use {@link org.hamcrest.CoreMatchers#hasItems(Matcher...)}

147

*/

148

@Deprecated

149

public static <T> Matcher<Iterable<T>> hasItems(Matcher<? super T>... elementMatchers);

150

151

/**

152

* Matcher for collection where every element matches the given matcher

153

* @param elementMatcher - Matcher that each element must match

154

* @return Matcher that matches collections where all elements match

155

* @deprecated use {@link org.hamcrest.CoreMatchers#everyItem(Matcher)}

156

*/

157

@Deprecated

158

public static <T> Matcher<Iterable<T>> everyItem(Matcher<T> elementMatcher);

159

160

/**

161

* Matcher for string containing substring

162

* @param substring - Substring to find

163

* @return Matcher that matches strings containing substring

164

* @deprecated use {@link org.hamcrest.CoreMatchers#containsString(String)}

165

*/

166

@Deprecated

167

public static Matcher<String> containsString(String substring);

168

169

/**

170

* Combine two matchers with AND

171

* @param matcher - First matcher

172

* @return CombinableBothMatcher for chaining

173

* @deprecated use {@link org.hamcrest.CoreMatchers#both(Matcher)}

174

*/

175

@Deprecated

176

public static <T> CombinableBothMatcher<T> both(Matcher<? super T> matcher);

177

178

/**

179

* Combine two matchers with OR

180

* @param matcher - First matcher

181

* @return CombinableEitherMatcher for chaining

182

* @deprecated use {@link org.hamcrest.CoreMatchers#either(Matcher)}

183

*/

184

@Deprecated

185

public static <T> CombinableEitherMatcher<T> either(Matcher<? super T> matcher);

186

187

/**

188

* Matcher for throwable with matching cause, appending stacktrace on mismatch

189

* @param throwableMatcher - Matcher for the throwable

190

* @return Matcher for Throwable

191

*/

192

public static <T extends Throwable> Matcher<T> isThrowable(Matcher<T> throwableMatcher);

193

194

/**

195

* Matcher for exception with matching cause, appending stacktrace on mismatch

196

* @param exceptionMatcher - Matcher for the exception

197

* @return Matcher for Exception

198

*/

199

public static <T extends Exception> Matcher<T> isException(Matcher<T> exceptionMatcher);

200

}

201

```

202

203

**Usage Examples:**

204

205

```java

206

import org.junit.Test;

207

import org.junit.matchers.JUnitMatchers;

208

import static org.junit.Assert.assertThat;

209

import static org.hamcrest.CoreMatchers.*;

210

211

public class JUnitMatchersTest {

212

@Test

213

public void testStringMatcher() {

214

assertThat("hello world", JUnitMatchers.containsString("world"));

215

assertThat("hello world", JUnitMatchers.containsString("hello"));

216

}

217

218

@Test

219

public void testCombinedMatchers() {

220

// Both conditions must be true

221

assertThat(5, JUnitMatchers.both(greaterThan(0)).and(lessThan(10)));

222

223

// Either condition can be true

224

assertThat(5, JUnitMatchers.either(is(5)).or(is(10)));

225

}

226

227

@Test

228

public void testExceptionMatchers() {

229

Exception ex = new RuntimeException("Error", new IOException("IO failed"));

230

231

assertThat(ex, JUnitMatchers.isException(

232

isA(RuntimeException.class)

233

));

234

}

235

}

236

```

237

238

### Common Hamcrest Matchers

239

240

Core matchers from Hamcrest library commonly used with JUnit.

241

242

```java { .api }

243

// Object matchers

244

Matcher<T> equalTo(T operand);

245

Matcher<T> is(T value);

246

Matcher<T> not(T value);

247

Matcher<Object> nullValue();

248

Matcher<Object> notNullValue();

249

Matcher<T> sameInstance(T target);

250

Matcher<T> instanceOf(Class<?> type);

251

Matcher<T> any(Class<T> type);

252

253

// Comparable matchers

254

Matcher<T> greaterThan(T value);

255

Matcher<T> greaterThanOrEqualTo(T value);

256

Matcher<T> lessThan(T value);

257

Matcher<T> lessThanOrEqualTo(T value);

258

259

// String matchers

260

Matcher<String> containsString(String substring);

261

Matcher<String> startsWith(String prefix);

262

Matcher<String> endsWith(String suffix);

263

Matcher<String> equalToIgnoringCase(String expectedString);

264

Matcher<String> equalToIgnoringWhiteSpace(String expectedString);

265

Matcher<String> isEmptyString();

266

Matcher<String> isEmptyOrNullString();

267

268

// Collection matchers

269

Matcher<Collection<T>> hasItem(T item);

270

Matcher<Collection<T>> hasItems(T... items);

271

Matcher<Collection<T>> empty();

272

Matcher<Collection<T>> hasSize(int size);

273

Matcher<Iterable<T>> contains(T... items);

274

Matcher<Iterable<T>> containsInAnyOrder(T... items);

275

276

// Array matchers

277

Matcher<T[]> arrayContaining(T... items);

278

Matcher<T[]> arrayContainingInAnyOrder(T... items);

279

Matcher<T[]> arrayWithSize(int size);

280

Matcher<T[]> emptyArray();

281

282

// Logical matchers

283

Matcher<T> allOf(Matcher<? super T>... matchers);

284

Matcher<T> anyOf(Matcher<? super T>... matchers);

285

Matcher<T> not(Matcher<T> matcher);

286

287

// Number matchers

288

Matcher<Double> closeTo(double operand, double error);

289

```

290

291

**Usage Examples:**

292

293

```java

294

import org.junit.Test;

295

import static org.junit.Assert.assertThat;

296

import static org.hamcrest.Matchers.*;

297

298

public class HamcrestMatchersTest {

299

@Test

300

public void testObjectMatchers() {

301

assertThat(5, equalTo(5));

302

assertThat(5, is(5));

303

assertThat(null, nullValue());

304

assertThat("text", notNullValue());

305

assertThat("text", instanceOf(String.class));

306

assertThat("text", any(String.class));

307

308

String s1 = "hello";

309

String s2 = s1;

310

assertThat(s1, sameInstance(s2));

311

}

312

313

@Test

314

public void testComparableMatchers() {

315

assertThat(10, greaterThan(5));

316

assertThat(10, greaterThanOrEqualTo(10));

317

assertThat(5, lessThan(10));

318

assertThat(5, lessThanOrEqualTo(5));

319

}

320

321

@Test

322

public void testStringMatchers() {

323

assertThat("hello world", containsString("world"));

324

assertThat("hello world", startsWith("hello"));

325

assertThat("hello world", endsWith("world"));

326

assertThat("HELLO", equalToIgnoringCase("hello"));

327

assertThat("hello world", equalToIgnoringWhiteSpace("hello world"));

328

assertThat("", isEmptyString());

329

assertThat(null, isEmptyOrNullString());

330

}

331

332

@Test

333

public void testCollectionMatchers() {

334

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

335

336

assertThat(items, hasItem("banana"));

337

assertThat(items, hasItems("apple", "cherry"));

338

assertThat(items, hasSize(3));

339

assertThat(items, not(empty()));

340

assertThat(items, contains("apple", "banana", "cherry"));

341

assertThat(items, containsInAnyOrder("cherry", "apple", "banana"));

342

}

343

344

@Test

345

public void testArrayMatchers() {

346

String[] array = {"a", "b", "c"};

347

348

assertThat(array, arrayContaining("a", "b", "c"));

349

assertThat(array, arrayContainingInAnyOrder("c", "a", "b"));

350

assertThat(array, arrayWithSize(3));

351

assertThat(new String[0], emptyArray());

352

}

353

354

@Test

355

public void testLogicalMatchers() {

356

// All conditions must be true

357

assertThat(5, allOf(greaterThan(0), lessThan(10), not(equalTo(7))));

358

359

// At least one condition must be true

360

assertThat(5, anyOf(equalTo(5), equalTo(10), equalTo(15)));

361

362

// Negation

363

assertThat(5, not(equalTo(10)));

364

assertThat(5, not(lessThan(0)));

365

}

366

367

@Test

368

public void testNumberMatchers() {

369

// Floating point comparison with tolerance

370

assertThat(3.14159, closeTo(3.14, 0.01));

371

assertThat(0.33333, closeTo(1.0/3.0, 0.001));

372

}

373

}

374

```

375

376

### Custom Matchers

377

378

Create custom matchers for domain-specific assertions.

379

380

```java { .api }

381

/**

382

* Base class for custom matchers

383

*/

384

public abstract class TypeSafeMatcher<T> extends BaseMatcher<T> {

385

/**

386

* Check if item matches

387

* @param item - Item to check

388

* @return true if matches

389

*/

390

protected abstract boolean matchesSafely(T item);

391

392

/**

393

* Describe the matcher

394

* @param description - Description to append to

395

*/

396

public abstract void describeTo(Description description);

397

398

/**

399

* Describe mismatch

400

* @param item - Item that didn't match

401

* @param mismatchDescription - Description to append to

402

*/

403

protected void describeMismatchSafely(T item, Description mismatchDescription);

404

}

405

```

406

407

**Usage Examples:**

408

409

```java

410

import org.hamcrest.Description;

411

import org.hamcrest.TypeSafeMatcher;

412

import org.hamcrest.Matcher;

413

import org.junit.Test;

414

import static org.junit.Assert.assertThat;

415

416

// Custom matcher for even numbers

417

public class IsEven extends TypeSafeMatcher<Integer> {

418

@Override

419

protected boolean matchesSafely(Integer number) {

420

return number % 2 == 0;

421

}

422

423

@Override

424

public void describeTo(Description description) {

425

description.appendText("an even number");

426

}

427

428

@Override

429

protected void describeMismatchSafely(Integer item, Description mismatchDescription) {

430

mismatchDescription.appendValue(item).appendText(" is odd");

431

}

432

433

public static Matcher<Integer> even() {

434

return new IsEven();

435

}

436

}

437

438

// Custom matcher for valid email

439

public class IsValidEmail extends TypeSafeMatcher<String> {

440

@Override

441

protected boolean matchesSafely(String email) {

442

return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$");

443

}

444

445

@Override

446

public void describeTo(Description description) {

447

description.appendText("a valid email address");

448

}

449

450

public static Matcher<String> validEmail() {

451

return new IsValidEmail();

452

}

453

}

454

455

// Custom matcher for range

456

public class InRange extends TypeSafeMatcher<Integer> {

457

private final int min;

458

private final int max;

459

460

public InRange(int min, int max) {

461

this.min = min;

462

this.max = max;

463

}

464

465

@Override

466

protected boolean matchesSafely(Integer value) {

467

return value >= min && value <= max;

468

}

469

470

@Override

471

public void describeTo(Description description) {

472

description.appendText("a value between ")

473

.appendValue(min)

474

.appendText(" and ")

475

.appendValue(max);

476

}

477

478

@Override

479

protected void describeMismatchSafely(Integer item, Description mismatchDescription) {

480

mismatchDescription.appendValue(item)

481

.appendText(" is outside range [")

482

.appendValue(min)

483

.appendText(", ")

484

.appendValue(max)

485

.appendText("]");

486

}

487

488

public static Matcher<Integer> inRange(int min, int max) {

489

return new InRange(min, max);

490

}

491

}

492

493

// Usage of custom matchers

494

public class CustomMatcherTest {

495

@Test

496

public void testEvenMatcher() {

497

assertThat(4, IsEven.even());

498

assertThat(2, IsEven.even());

499

// assertThat(3, IsEven.even()); // Fails with "3 is odd"

500

}

501

502

@Test

503

public void testEmailMatcher() {

504

assertThat("user@example.com", IsValidEmail.validEmail());

505

assertThat("test.user@domain.co.uk", IsValidEmail.validEmail());

506

// assertThat("invalid.email", IsValidEmail.validEmail()); // Fails

507

}

508

509

@Test

510

public void testRangeMatcher() {

511

assertThat(5, InRange.inRange(1, 10));

512

assertThat(1, InRange.inRange(1, 10));

513

assertThat(10, InRange.inRange(1, 10));

514

// assertThat(15, InRange.inRange(1, 10)); // Fails with "15 is outside range [1, 10]"

515

}

516

}

517

518

// Complex custom matcher with parameters

519

public class HasProperty<T> extends TypeSafeMatcher<T> {

520

private final String propertyName;

521

private final Matcher<?> valueMatcher;

522

523

public HasProperty(String propertyName, Matcher<?> valueMatcher) {

524

this.propertyName = propertyName;

525

this.valueMatcher = valueMatcher;

526

}

527

528

@Override

529

protected boolean matchesSafely(T obj) {

530

try {

531

String getterName = "get" + capitalize(propertyName);

532

Method getter = obj.getClass().getMethod(getterName);

533

Object value = getter.invoke(obj);

534

return valueMatcher.matches(value);

535

} catch (Exception e) {

536

return false;

537

}

538

}

539

540

@Override

541

public void describeTo(Description description) {

542

description.appendText("has property ")

543

.appendValue(propertyName)

544

.appendText(" matching ")

545

.appendDescriptionOf(valueMatcher);

546

}

547

548

public static <T> Matcher<T> hasProperty(String property, Matcher<?> matcher) {

549

return new HasProperty<>(property, matcher);

550

}

551

552

private String capitalize(String str) {

553

return str.substring(0, 1).toUpperCase() + str.substring(1);

554

}

555

}

556

557

// Usage

558

@Test

559

public void testPropertyMatcher() {

560

User user = new User("Alice", 25);

561

assertThat(user, HasProperty.hasProperty("name", equalTo("Alice")));

562

assertThat(user, HasProperty.hasProperty("age", greaterThan(18)));

563

}

564

```

565

566

### Matcher Composition

567

568

Combine matchers to create complex assertions.

569

570

**Usage Examples:**

571

572

```java

573

import org.junit.Test;

574

import static org.junit.Assert.assertThat;

575

import static org.hamcrest.Matchers.*;

576

577

public class MatcherCompositionTest {

578

@Test

579

public void testComplexComposition() {

580

List<String> items = Arrays.asList("apple", "banana", "apricot", "avocado");

581

582

// All items start with 'a' and have length > 5

583

assertThat(items, everyItem(

584

allOf(

585

startsWith("a"),

586

hasLength(greaterThan(5))

587

)

588

));

589

590

// At least one item equals "banana"

591

assertThat(items, hasItem(equalTo("banana")));

592

593

// Collection has size 4 and contains "apple"

594

assertThat(items, allOf(

595

hasSize(4),

596

hasItem("apple")

597

));

598

}

599

600

@Test

601

public void testNestedMatchers() {

602

Map<String, Integer> scores = new HashMap<>();

603

scores.put("Alice", 95);

604

scores.put("Bob", 87);

605

scores.put("Charlie", 92);

606

607

assertThat(scores, allOf(

608

hasEntry("Alice", 95),

609

hasKey("Bob"),

610

hasValue(greaterThan(85))

611

));

612

}

613

614

@Test

615

public void testObjectPropertyMatchers() {

616

User user = new User("Alice", 25, "alice@example.com");

617

618

assertThat(user, allOf(

619

hasProperty("name", startsWith("A")),

620

hasProperty("age", both(greaterThan(18)).and(lessThan(100))),

621

hasProperty("email", containsString("@"))

622

));

623

}

624

}

625

```

626

627

## Benefits of Using Matchers

628

629

### Improved Readability

630

631

```java

632

// Without matchers

633

assertTrue(result.size() > 0);

634

assertTrue(result.contains("expected"));

635

636

// With matchers - more readable

637

assertThat(result, not(empty()));

638

assertThat(result, hasItem("expected"));

639

```

640

641

### Better Error Messages

642

643

```java

644

// Without matchers

645

// Expected: true but was: false

646

assertTrue(name.startsWith("Mr"));

647

648

// With matchers - more descriptive

649

// Expected: a string starting with "Mr" but: was "Ms Smith"

650

assertThat(name, startsWith("Mr"));

651

```

652

653

### Composable Assertions

654

655

```java

656

// Multiple separate assertions

657

assertTrue(age >= 18);

658

assertTrue(age <= 65);

659

assertNotNull(name);

660

assertTrue(name.length() > 0);

661

662

// Single composed assertion

663

assertThat(age, allOf(greaterThanOrEqualTo(18), lessThanOrEqualTo(65)));

664

assertThat(name, allOf(notNullValue(), not(isEmptyString())));

665

```

666

667

## Types

668

669

```java { .api }

670

/**

671

* Base matcher interface

672

*/

673

public interface Matcher<T> extends SelfDescribing {

674

boolean matches(Object item);

675

void describeMismatch(Object item, Description mismatchDescription);

676

677

@Deprecated

678

void _dont_implement_Matcher___instead_extend_BaseMatcher_();

679

}

680

681

/**

682

* Base class for matchers

683

*/

684

public abstract class BaseMatcher<T> implements Matcher<T> {

685

@Override

686

public void describeMismatch(Object item, Description description);

687

688

@Override

689

public String toString();

690

}

691

692

/**

693

* Matcher description

694

*/

695

public interface Description {

696

Description appendText(String text);

697

Description appendDescriptionOf(SelfDescribing value);

698

Description appendValue(Object value);

699

Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values);

700

}

701

702

/**

703

* Combinable matcher for both/and

704

*/

705

public class CombinableBothMatcher<T> {

706

public CombinableMatcher<T> and(Matcher<? super T> matcher);

707

}

708

709

/**

710

* Combinable matcher for either/or

711

*/

712

public class CombinableEitherMatcher<T> {

713

public CombinableMatcher<T> or(Matcher<? super T> matcher);

714

}

715

716

/**

717

* Combined matcher result

718

*/

719

public class CombinableMatcher<T> extends TypeSafeMatcher<T> {

720

@Override

721

protected boolean matchesSafely(T item);

722

723

@Override

724

public void describeTo(Description description);

725

}

726

```

727