or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-assertions.mdcore-assertions.mdexception-handling.mdhamcrest-matchers.mdindex.mdtest-assumptions.mdtest-lifecycle.mdtest-runners.md

hamcrest-matchers.mddocs/

0

# Hamcrest Matchers

1

2

Hamcrest provides a library of matcher objects for building test expressions. Matchers offer readable and composable assertions with detailed failure messages that clearly describe what was expected versus what was actually encountered.

3

4

## Core Matcher Interface

5

6

```scala { .api }

7

trait Matcher[T] {

8

def matches(actual: AnyRef): Boolean

9

def describeTo(description: Description): Unit

10

}

11

12

trait Description {

13

def appendText(text: String): Description

14

def appendDescriptionOf(value: SelfDescribing): Description

15

def appendValue(value: AnyRef): Description

16

}

17

```

18

19

## Matcher Factories

20

21

### CoreMatchers Object

22

23

```scala { .api }

24

object CoreMatchers {

25

def is[T](matcher: Matcher[T]): Matcher[T]

26

def is[T](value: T): Matcher[T]

27

def isA[T](typ: Class[T]): Matcher[T]

28

def any[T](typ: Class[T]): Matcher[T]

29

def instanceOf[T](typ: Class[_]): Matcher[T]

30

def not[T](matcher: Matcher[T]): Matcher[T]

31

def not[T](value: T): Matcher[T]

32

def notNullValue(): Matcher[AnyRef]

33

def notNullValue[T](typ: Class[T]): Matcher[T]

34

def nullValue(): Matcher[AnyRef]

35

def nullValue[T](typ: Class[T]): Matcher[T]

36

def equalTo[T](operand: T): Matcher[T]

37

def equalToObject(operand: AnyRef): Matcher[AnyRef]

38

}

39

```

40

41

## Basic Matchers

42

43

### Identity and Decoration

44

45

```scala { .api }

46

def is[T](matcher: Matcher[T]): Matcher[T]

47

def is[T](value: T): Matcher[T]

48

```

49

50

**Usage:**

51

```scala

52

import org.hamcrest.CoreMatchers._

53

import org.junit.Assert.assertThat

54

55

assertThat(userName, is("admin"))

56

assertThat(userAge, is(greaterThan(18)))

57

assertThat(result, is(notNullValue()))

58

```

59

60

The `is` matcher is purely decorative - it wraps another matcher to improve readability without changing behavior.

61

62

### Type Checking

63

64

```scala { .api }

65

def any[T](typ: Class[T]): Matcher[T]

66

def instanceOf[T](typ: Class[_]): Matcher[T]

67

def isA[T](typ: Class[T]): Matcher[T]

68

```

69

70

**Usage:**

71

```scala

72

assertThat(result, instanceOf(classOf[String]))

73

assertThat(exception, isA(classOf[IllegalArgumentException]))

74

assertThat(value, any(classOf[Number]))

75

```

76

77

- `instanceOf`: Matches if the actual value is an instance of the specified class

78

- `isA`: Alias for `instanceOf` with decorative "is a" reading

79

- `any`: Matches any instance of the specified type

80

81

## Null Value Matchers

82

83

```scala { .api }

84

def nullValue(): Matcher[AnyRef]

85

def nullValue[T](typ: Class[T]): Matcher[T]

86

def notNullValue(): Matcher[AnyRef]

87

def notNullValue[T](typ: Class[T]): Matcher[T]

88

```

89

90

**Usage:**

91

```scala

92

assertThat(optionalValue, nullValue())

93

assertThat(optionalValue, nullValue(classOf[String]))

94

assertThat(requiredField, notNullValue())

95

assertThat(user.getName(), notNullValue(classOf[String]))

96

```

97

98

## Negation Matcher

99

100

```scala { .api }

101

def not[T](matcher: Matcher[T]): Matcher[T]

102

def not[T](value: T): Matcher[T]

103

```

104

105

**Usage:**

106

```scala

107

assertThat(result, not(nullValue()))

108

assertThat(status, not("inactive"))

109

assertThat(age, not(lessThan(0)))

110

```

111

112

The `not` matcher inverts any other matcher, providing clear negation with appropriate error messages.

113

114

## Matcher Integration with Assert

115

116

```scala { .api }

117

def assertThat[T](actual: T, matcher: Matcher[T]): Unit

118

def assertThat[T](reason: String, actual: T, matcher: Matcher[T]): Unit

119

```

120

121

**Usage:**

122

```scala

123

// Basic matcher assertion

124

assertThat(result.size(), is(5))

125

126

// With custom message

127

assertThat("User list should not be empty", users, not(nullValue()))

128

129

// Composed matchers

130

assertThat(user.getStatus(), is(not("inactive")))

131

assertThat(response.getCode(), is(instanceOf(classOf[Integer])))

132

```

133

134

## Advanced Matcher Classes

135

136

### Base Matcher Implementation

137

138

```scala { .api }

139

abstract class BaseMatcher[T] extends Matcher[T] {

140

def describeTo(description: Description): Unit

141

def matches(actual: AnyRef): Boolean

142

}

143

```

144

145

### Diagnosing Matcher

146

147

```scala { .api }

148

abstract class DiagnosingMatcher[T] extends BaseMatcher[T] {

149

def matches(item: AnyRef, mismatchDescription: Description): Boolean

150

final def matches(item: AnyRef): Boolean

151

}

152

```

153

154

DiagnosingMatcher provides enhanced mismatch descriptions by allowing matchers to describe why a match failed.

155

156

## Matcher Assertions vs Regular Assertions

157

158

**Regular Assert:**

159

```scala

160

assertEquals("Expected active user", "active", user.getStatus())

161

// Error: Expected active user expected:<active> but was:<inactive>

162

```

163

164

**Hamcrest Matcher:**

165

```scala

166

assertThat(user.getStatus(), is("active"))

167

// Error: Expected: is "active" but: was "inactive"

168

```

169

170

Hamcrest matchers provide:

171

- More readable error messages

172

- Composable expressions

173

- Better type safety

174

- Consistent failure reporting format

175

176

## Custom Matcher Implementation

177

178

```scala

179

import org.hamcrest.{Description, BaseMatcher}

180

181

class GreaterThanMatcher(threshold: Int) extends BaseMatcher[Int] {

182

def matches(actual: AnyRef): Boolean = {

183

actual.asInstanceOf[Int] > threshold

184

}

185

186

def describeTo(description: Description): Unit = {

187

description.appendText(s"greater than $threshold")

188

}

189

}

190

191

def greaterThan(threshold: Int): Matcher[Int] = new GreaterThanMatcher(threshold)

192

193

// Usage

194

assertThat(score, greaterThan(80))

195

```

196

197

## Error Reporting and Description

198

199

Hamcrest matchers automatically generate descriptive error messages:

200

201

- **Expected**: What the matcher was looking for

202

- **Actual**: What was actually provided

203

- **Mismatch**: Why the match failed (for DiagnosingMatcher)

204

205

This provides clear, consistent test failure reporting across all matcher types.