0
# Test Appenders
1
2
Test appenders for capturing and analyzing log events during testing. These specialized appenders provide essential functionality for verifying logging behavior, testing error scenarios, and validating threading behavior in Log4j applications.
3
4
## Capabilities
5
6
### ListAppender
7
8
The primary test appender for capturing log events in memory. Provides thread-safe collection of events, messages, and raw data with immutable snapshot access.
9
10
```java { .api }
11
/**
12
* Primary test appender that collects log events in lists for verification
13
* Plugin annotation: @Plugin(name = "List", category = Core.CATEGORY_NAME)
14
*/
15
@Plugin(name = "List", category = Core.CATEGORY_NAME)
16
public class ListAppender extends AbstractAppender {
17
18
/**
19
* Returns immutable snapshot of captured log events
20
* @return List of LogEvent objects
21
*/
22
public List<LogEvent> getEvents();
23
24
/**
25
* Returns immutable snapshot of formatted log messages
26
* @return List of formatted message strings
27
*/
28
public List<String> getMessages();
29
30
/**
31
* Returns immutable snapshot of raw serialized data
32
* @return List of byte arrays containing serialized data
33
*/
34
public List<byte[]> getData();
35
36
/**
37
* Clears all captured data and resets the appender
38
* @return This ListAppender instance for method chaining
39
*/
40
public ListAppender clear();
41
42
/**
43
* Retrieves a named ListAppender instance from the logger context
44
* @param name The name of the appender to retrieve
45
* @return The named ListAppender instance or null if not found
46
*/
47
public static ListAppender getListAppender(String name);
48
49
/**
50
* CountDownLatch for synchronizing asynchronous testing scenarios
51
* Volatile field for thread-safe access during concurrent testing
52
*/
53
public volatile CountDownLatch countDownLatch;
54
}
55
```
56
57
**Usage Examples:**
58
59
```java
60
import org.apache.logging.log4j.core.test.appender.ListAppender;
61
import org.apache.logging.log4j.core.test.junit.LoggerContextRule;
62
import org.junit.Rule;
63
import org.junit.Test;
64
65
public class ListAppenderTest {
66
67
@Rule
68
public LoggerContextRule context = new LoggerContextRule("log4j2-test.xml");
69
70
@Test
71
public void testEventCapture() {
72
ListAppender appender = context.getListAppender("TestList");
73
Logger logger = context.getLogger();
74
75
// Log some events
76
logger.info("Info message");
77
logger.warn("Warning message");
78
logger.error("Error message");
79
80
// Verify captured events
81
List<LogEvent> events = appender.getEvents();
82
assertEquals(3, events.size());
83
assertEquals(Level.INFO, events.get(0).getLevel());
84
assertEquals("Info message", events.get(0).getMessage().getFormattedMessage());
85
86
// Verify captured messages
87
List<String> messages = appender.getMessages();
88
assertEquals(3, messages.size());
89
assertTrue(messages.contains("Info message"));
90
91
// Clear for next test
92
appender.clear();
93
assertEquals(0, appender.getEvents().size());
94
}
95
96
@Test
97
public void testAsynchronousLogging() throws InterruptedException {
98
ListAppender appender = context.getListAppender("AsyncTestList");
99
appender.countDownLatch = new CountDownLatch(1);
100
101
Logger logger = context.getLogger();
102
logger.info("Async message");
103
104
// Wait for async processing
105
assertTrue(appender.countDownLatch.await(5, TimeUnit.SECONDS));
106
assertEquals(1, appender.getEvents().size());
107
}
108
}
109
```
110
111
### BlockingAppender
112
113
Appender that blocks on append operations for testing threading scenarios and deadlock detection.
114
115
```java { .api }
116
/**
117
* Appender that blocks for testing threading scenarios
118
* Plugin annotation: @Plugin(name = "Block", category = "Core")
119
*/
120
@Plugin(name = "Block", category = "Core")
121
public class BlockingAppender extends AbstractAppender {
122
123
/**
124
* Creates a blocking appender with the specified name
125
* @param name The name for the appender
126
* @return New BlockingAppender instance
127
*/
128
public static BlockingAppender createAppender(String name);
129
130
/**
131
* Indicates whether the appender is currently running/blocking
132
* Volatile field for thread-safe access
133
*/
134
public volatile boolean running;
135
}
136
```
137
138
### AlwaysFailAppender
139
140
Appender that always fails for testing error handling behavior.
141
142
```java { .api }
143
/**
144
* Appender that always fails for error handling testing
145
* Plugin annotation: @Plugin(name = "AlwaysFail", category = "Core")
146
*/
147
@Plugin(name = "AlwaysFail", category = "Core")
148
public class AlwaysFailAppender extends AbstractAppender {
149
150
/**
151
* Creates an appender that always fails on append operations
152
* @param name The name for the appender
153
* @return New AlwaysFailAppender instance
154
*/
155
public static AlwaysFailAppender createAppender(String name);
156
}
157
```
158
159
### FailOnceAppender
160
161
Appender that fails once then succeeds for testing resilience and recovery behavior.
162
163
```java { .api }
164
/**
165
* Appender that fails once then succeeds for resilience testing
166
* Plugin annotation: @Plugin(name = "FailOnce", category = "Core")
167
*/
168
@Plugin(name = "FailOnce", category = "Core")
169
public class FailOnceAppender extends AbstractAppender {
170
171
/**
172
* Creates an appender that fails on first append then succeeds
173
* @param name The name for the appender
174
* @return New FailOnceAppender instance
175
*/
176
public static FailOnceAppender createAppender(String name);
177
178
/**
179
* Enum defining types of exceptions to throw on failure
180
*/
181
public enum ThrowableClassName {
182
RUNTIME_EXCEPTION,
183
LOGGING_EXCEPTION,
184
IO_EXCEPTION
185
}
186
}
187
```
188
189
### InMemoryAppender
190
191
Memory-based appender for testing output stream functionality.
192
193
```java { .api }
194
/**
195
* Memory-based appender extending AbstractOutputStreamAppender
196
*/
197
public class InMemoryAppender extends AbstractOutputStreamAppender {
198
199
/**
200
* Creates an in-memory appender for testing stream operations
201
* @param name The name for the appender
202
* @param layout The layout to use for formatting
203
* @return New InMemoryAppender instance
204
*/
205
public static InMemoryAppender createAppender(String name, Layout<? extends Serializable> layout);
206
207
/**
208
* Gets the captured output as a string
209
* @return String representation of captured output
210
*/
211
public String getOutput();
212
213
/**
214
* OutputStreamManager implementation for memory-based operations
215
*/
216
public static class InMemoryManager extends OutputStreamManager {
217
public byte[] getBytes();
218
public String getString();
219
}
220
}
221
```
222
223
### EncodingListAppender
224
225
ListAppender with encoding support for testing character encoding scenarios.
226
227
```java { .api }
228
/**
229
* ListAppender with encoding support
230
* Extends ListAppender with character encoding capabilities
231
*/
232
public class EncodingListAppender extends ListAppender {
233
234
/**
235
* Creates an encoding-aware list appender
236
* @param name The name for the appender
237
* @param encoding The character encoding to use
238
* @return New EncodingListAppender instance
239
*/
240
public static EncodingListAppender createAppender(String name, String encoding);
241
242
/**
243
* Gets the character encoding used by this appender
244
* @return The character encoding name
245
*/
246
public String getEncoding();
247
}
248
```
249
250
## Usage Patterns
251
252
### Basic Event Verification
253
254
```java
255
// Configure ListAppender in log4j2-test.xml
256
ListAppender appender = context.getListAppender("TestAppender");
257
Logger logger = context.getLogger();
258
259
logger.info("Test message");
260
261
List<LogEvent> events = appender.getEvents();
262
assertEquals(1, events.size());
263
assertEquals(Level.INFO, events.get(0).getLevel());
264
```
265
266
### Error Handling Testing
267
268
```java
269
// Use AlwaysFailAppender to test error handling
270
AlwaysFailAppender failAppender = AlwaysFailAppender.createAppender("FailTest");
271
// Configure and test error scenarios
272
```
273
274
### Threading and Concurrency Testing
275
276
```java
277
// Use BlockingAppender for threading tests
278
BlockingAppender blockingAppender = BlockingAppender.createAppender("BlockTest");
279
// Test concurrent logging scenarios
280
```
281
282
### Resilience Testing
283
284
```java
285
// Use FailOnceAppender to test recovery
286
FailOnceAppender failOnceAppender = FailOnceAppender.createAppender("ResilienceTest");
287
// Test that logging recovers after initial failure
288
```