View Javadoc
1   package com.github.valfirst.slf4jtest;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.List;
6   import java.util.function.Supplier;
7   import org.slf4j.Logger;
8   import org.slf4j.Marker;
9   import org.slf4j.event.DefaultLoggingEvent;
10  import org.slf4j.event.KeyValuePair;
11  import org.slf4j.event.Level;
12  import org.slf4j.event.LoggingEvent;
13  import org.slf4j.helpers.CheckReturnValue;
14  import org.slf4j.spi.DefaultLoggingEventBuilder;
15  import org.slf4j.spi.LoggingEventBuilder;
16  
17  /**
18   * A {@link LoggingEventBuilder} which changes the following compared to {@link
19   * DefaultLoggingEventBuilder}:
20   *
21   * <ul>
22   *   <li>The {@link #toLoggingEvent} method is added to build the event without logging it.
23   *   <li>The return type of the fluent methods is {@link TestLoggingEventBuilder}. This allows
24   *       {@link #toLoggingEvent} to be used in a fluent manner.
25   *   <li>The {@link KeyValuePair} implementation overrides the {@link Object#equals} and {@link
26   *       Object#hashCode} methods. This allows tests for equality in test assertions.
27   * </ul>
28   */
29  public class TestLoggingEventBuilder extends DefaultLoggingEventBuilder {
30  
31      public TestLoggingEventBuilder(Logger logger, Level level) {
32          super(logger, level);
33          loggingEvent = new TestLoggingEvent(level, logger);
34      }
35  
36      /** Build the event, without logging it. */
37      public LoggingEvent toLoggingEvent() {
38          return loggingEvent;
39      }
40  
41      static class TestLoggingEvent extends DefaultLoggingEvent {
42  
43          private List<KeyValuePair> keyValuePairs = null;
44  
45          public TestLoggingEvent(Level level, Logger logger) {
46              super(level, logger);
47          }
48  
49          @Override
50          public void addKeyValue(String key, Object value) {
51              if (keyValuePairs == null) {
52                  keyValuePairs = new ArrayList<>();
53              }
54              keyValuePairs.add(new TestKeyValuePair(key, value));
55          }
56  
57          @Override
58          public List<KeyValuePair> getKeyValuePairs() {
59              return keyValuePairs;
60          }
61      }
62  
63      /**
64       * Extension of {@link KeyValuePair} with overridden {@link Object#equals} and {@link
65       * Object#hashCode} methods. This class must be used on the left hand side of {@link
66       * Object#equals} instead of {@link KeyValuePair}. {@link KeyValuePair} can be used on the right
67       * hand side.
68       */
69      public static class TestKeyValuePair extends KeyValuePair {
70          public TestKeyValuePair(String key, Object value) {
71              super(key, value);
72          }
73  
74          @Override
75          public boolean equals(Object o) {
76              if (this == o) {
77                  return true;
78              }
79              if (!(o instanceof KeyValuePair)) {
80                  return false;
81              }
82              KeyValuePair that = (KeyValuePair) o;
83              return Arrays.deepEquals(new Object[] {key, value}, new Object[] {that.key, that.value});
84          }
85  
86          @Override
87          public int hashCode() {
88              return Arrays.deepHashCode(new Object[] {key, value});
89          }
90      }
91  
92      @CheckReturnValue
93      @Override
94      @SuppressWarnings("unchecked")
95      public TestLoggingEventBuilder setCause(Throwable cause) {
96          return (TestLoggingEventBuilder) super.setCause(cause);
97      }
98  
99      @CheckReturnValue
100     @Override
101     public TestLoggingEventBuilder addMarker(Marker marker) {
102         return (TestLoggingEventBuilder) super.addMarker(marker);
103     }
104 
105     @CheckReturnValue
106     @Override
107     @SuppressWarnings("unchecked")
108     public TestLoggingEventBuilder addArgument(Object p) {
109         return (TestLoggingEventBuilder) super.addArgument(p);
110     }
111 
112     @CheckReturnValue
113     @Override
114     @SuppressWarnings("unchecked")
115     public TestLoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
116         return (TestLoggingEventBuilder) super.addArgument(objectSupplier);
117     }
118 
119     @CheckReturnValue
120     @Override
121     @SuppressWarnings("unchecked")
122     public TestLoggingEventBuilder addKeyValue(String key, Object value) {
123         return (TestLoggingEventBuilder) super.addKeyValue(key, value);
124     }
125 
126     @CheckReturnValue
127     @Override
128     @SuppressWarnings("unchecked")
129     public TestLoggingEventBuilder addKeyValue(String key, Supplier<Object> valueSupplier) {
130         return (TestLoggingEventBuilder) super.addKeyValue(key, valueSupplier);
131     }
132 
133     @CheckReturnValue
134     @Override
135     @SuppressWarnings("unchecked")
136     public TestLoggingEventBuilder setMessage(String message) {
137         return (TestLoggingEventBuilder) super.setMessage(message);
138     }
139 
140     @CheckReturnValue
141     @Override
142     @SuppressWarnings("unchecked")
143     public TestLoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
144         return (TestLoggingEventBuilder) super.setMessage(messageSupplier);
145     }
146 }