or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

hamcrest-matchers.mdindex.mdjunit-integration.mdmock-servers.mdtest-appenders.mdtest-categories.mdtesting-utilities.md

hamcrest-matchers.mddocs/

0

# Hamcrest Matchers

1

2

Custom Hamcrest matchers for file-based assertions and Map testing, providing fluent assertion APIs for common testing scenarios in Log4j applications.

3

4

## Capabilities

5

6

### File Matchers

7

8

Hamcrest matchers for File objects, enabling fluent file-based assertions in tests.

9

10

```java { .api }

11

/**

12

* Hamcrest matchers for File objects

13

*/

14

public final class FileMatchers {

15

16

/**

17

* Matches if file exists

18

* @return Matcher that succeeds if file exists

19

*/

20

public static Matcher<File> exists();

21

22

/**

23

* Matches file length against provided matcher

24

* @param lengthMatcher Matcher for file length in bytes

25

* @return Matcher that checks file length

26

*/

27

public static Matcher<File> hasLength(Matcher<Long> lengthMatcher);

28

29

/**

30

* Matches if file is empty (length = 0)

31

* @return Matcher that succeeds if file is empty

32

*/

33

public static Matcher<File> isEmpty();

34

35

/**

36

* Matches file last modified time against provided matcher

37

* @param lastModifiedMatcher Matcher for last modified timestamp

38

* @return Matcher that checks last modified time

39

*/

40

public static Matcher<File> lastModified(Matcher<Long> lastModifiedMatcher);

41

42

/**

43

* Matches if directory contains files (not empty directory)

44

* @return Matcher that succeeds if directory has files

45

*/

46

public static Matcher<File> hasFiles();

47

48

/**

49

* Matches file name against provided matcher

50

* @param nameMatcher Matcher for file name string

51

* @return Matcher that checks file name

52

*/

53

public static Matcher<File> hasName(Matcher<String> nameMatcher);

54

}

55

```

56

57

**File Matcher Usage Examples:**

58

59

```java

60

import org.apache.logging.log4j.core.test.hamcrest.FileMatchers;

61

import static org.hamcrest.MatcherAssert.assertThat;

62

import static org.hamcrest.Matchers.*;

63

64

public class FileMatcherTest {

65

66

@Test

67

public void testLogFileCreation() {

68

File logFile = new File("test.log");

69

70

// Verify log file exists after logging

71

Logger logger = LogManager.getLogger();

72

logger.info("Test message");

73

74

assertThat(logFile, FileMatchers.exists());

75

assertThat(logFile, FileMatchers.hasLength(greaterThan(0L)));

76

assertThat(logFile, not(FileMatchers.isEmpty()));

77

}

78

79

@Test

80

public void testLogFileRotation() throws InterruptedException {

81

File logFile = new File("rolling.log");

82

long beforeTime = System.currentTimeMillis();

83

84

Logger logger = LogManager.getLogger();

85

logger.info("Message before rotation");

86

87

Thread.sleep(10); // Ensure time difference

88

89

// Trigger rotation

90

logger.info("Message after rotation");

91

92

assertThat(logFile, FileMatchers.exists());

93

assertThat(logFile, FileMatchers.lastModified(greaterThan(beforeTime)));

94

}

95

96

@Test

97

public void testLogDirectory() {

98

File logDir = new File("logs");

99

100

// After logging to directory

101

Logger logger = LogManager.getLogger();

102

logger.info("Directory test message");

103

104

assertThat(logDir, FileMatchers.exists());

105

assertThat(logDir, FileMatchers.hasFiles());

106

}

107

108

@Test

109

public void testLogFileName() {

110

File logFile = new File("application-2023-12-01.log");

111

112

assertThat(logFile, FileMatchers.hasName(startsWith("application")));

113

assertThat(logFile, FileMatchers.hasName(endsWith(".log")));

114

assertThat(logFile, FileMatchers.hasName(containsString("2023")));

115

}

116

117

@Test

118

public void testEmptyLogFile() {

119

File emptyLog = new File("empty.log");

120

emptyLog.createNewFile(); // Create empty file

121

122

assertThat(emptyLog, FileMatchers.exists());

123

assertThat(emptyLog, FileMatchers.isEmpty());

124

assertThat(emptyLog, FileMatchers.hasLength(equalTo(0L)));

125

}

126

}

127

```

128

129

### Map Matchers

130

131

Hamcrest matchers for Map objects, useful for testing structured logging data and MDC contexts.

132

133

```java { .api }

134

/**

135

* Hamcrest matchers for Map objects

136

*/

137

public class MapMatchers {

138

139

/**

140

* Matches if map contains specified key

141

* @param key The key to check for

142

* @return Matcher that succeeds if map contains key

143

*/

144

public static <K> Matcher<Map<? super K, ?>> hasKey(K key);

145

146

/**

147

* Matches if map contains specified value

148

* @param value The value to check for

149

* @return Matcher that succeeds if map contains value

150

*/

151

public static <V> Matcher<Map<?, ? super V>> hasValue(V value);

152

153

/**

154

* Matches if map contains specified key-value pair

155

* @param key The key to check for

156

* @param value The expected value for the key

157

* @return Matcher that succeeds if map contains key-value pair

158

*/

159

public static <K, V> Matcher<Map<? super K, ? super V>> hasEntry(K key, V value);

160

161

/**

162

* Matches if map is empty

163

* @return Matcher that succeeds if map is empty

164

*/

165

public static Matcher<Map<?, ?>> isEmpty();

166

167

/**

168

* Matches map size against provided matcher

169

* @param sizeMatcher Matcher for map size

170

* @return Matcher that checks map size

171

*/

172

public static Matcher<Map<?, ?>> hasSize(Matcher<Integer> sizeMatcher);

173

}

174

```

175

176

**Map Matcher Usage Examples:**

177

178

```java

179

import org.apache.logging.log4j.core.test.hamcrest.MapMatchers;

180

import static org.hamcrest.MatcherAssert.assertThat;

181

182

public class MapMatcherTest {

183

184

@Test

185

public void testMDCContext() {

186

ThreadContext.put("userId", "12345");

187

ThreadContext.put("sessionId", "abcdef");

188

ThreadContext.put("requestId", "req-001");

189

190

Map<String, String> mdc = ThreadContext.getContext();

191

192

assertThat(mdc, MapMatchers.hasKey("userId"));

193

assertThat(mdc, MapMatchers.hasValue("12345"));

194

assertThat(mdc, MapMatchers.hasEntry("sessionId", "abcdef"));

195

assertThat(mdc, MapMatchers.hasSize(equalTo(3)));

196

assertThat(mdc, not(MapMatchers.isEmpty()));

197

}

198

199

@Test

200

public void testLogEventProperties() {

201

// Capture log event with properties

202

ListAppender appender = getListAppender("test");

203

Logger logger = LogManager.getLogger();

204

205

logger.info("Test message with properties");

206

207

LogEvent event = appender.getEvents().get(0);

208

Map<String, String> contextMap = event.getContextData().toMap();

209

210

assertThat(contextMap, MapMatchers.hasKey("threadName"));

211

assertThat(contextMap, not(MapMatchers.isEmpty()));

212

}

213

}

214

```

215

216

### Descriptors

217

218

Description utilities for enhanced Hamcrest matcher descriptions and error messages.

219

220

```java { .api }

221

/**

222

* Description utilities for Hamcrest matchers

223

*/

224

public class Descriptors {

225

226

/**

227

* Creates description for file properties

228

* @param file The file to describe

229

* @return String description of file properties

230

*/

231

public static String describeFile(File file);

232

233

/**

234

* Creates description for map contents

235

* @param map The map to describe

236

* @return String description of map contents

237

*/

238

public static String describeMap(Map<?, ?> map);

239

240

/**

241

* Creates description for collection contents

242

* @param collection The collection to describe

243

* @return String description of collection

244

*/

245

public static String describeCollection(Collection<?> collection);

246

247

/**

248

* Formats description with proper indentation

249

* @param description The description to format

250

* @param indentLevel Indentation level

251

* @return Formatted description string

252

*/

253

public static String formatDescription(String description, int indentLevel);

254

}

255

```

256

257

## Usage Patterns

258

259

### File Assertion Patterns

260

261

```java

262

// Basic file existence and content checks

263

assertThat(logFile, FileMatchers.exists());

264

assertThat(logFile, FileMatchers.hasLength(greaterThan(100L)));

265

assertThat(logFile, not(FileMatchers.isEmpty()));

266

267

// File naming patterns

268

assertThat(logFile, FileMatchers.hasName(startsWith("app")));

269

assertThat(logFile, FileMatchers.hasName(endsWith(".log")));

270

271

// Directory and file system checks

272

assertThat(logDir, FileMatchers.hasFiles());

273

assertThat(backupFile, FileMatchers.lastModified(greaterThan(startTime)));

274

```

275

276

### Combined Matcher Patterns

277

278

```java

279

// Combining multiple matchers

280

assertThat(logFile, allOf(

281

FileMatchers.exists(),

282

FileMatchers.hasLength(greaterThan(0L)),

283

FileMatchers.hasName(containsString("application"))

284

));

285

286

// Either/or scenarios

287

assertThat(configFile, either(

288

FileMatchers.hasName(endsWith(".xml"))

289

).or(

290

FileMatchers.hasName(endsWith(".json"))

291

));

292

```

293

294

### MDC and Context Testing

295

296

```java

297

// Test MDC content

298

Map<String, String> mdc = ThreadContext.getContext();

299

assertThat(mdc, allOf(

300

MapMatchers.hasKey("userId"),

301

MapMatchers.hasEntry("action", "login"),

302

MapMatchers.hasSize(greaterThan(2))

303

));

304

305

// Test log event context

306

LogEvent event = appender.getEvents().get(0);

307

Map<String, String> contextData = event.getContextData().toMap();

308

assertThat(contextData, MapMatchers.hasEntry("traceId", expectedTraceId));

309

```

310

311

### Custom Matcher Integration

312

313

```java

314

// Combining with standard Hamcrest matchers

315

assertThat(logFile, both(

316

FileMatchers.exists()

317

).and(

318

FileMatchers.hasLength(between(100L, 1000L))

319

));

320

321

// Negation patterns

322

assertThat(tempLogFile, not(anyOf(

323

FileMatchers.isEmpty(),

324

FileMatchers.hasName(containsString("production"))

325

)));

326

```