Add StringAppender Logback Appender implementation to capture log messages in-memory appended to a String.
Resolve gh-73.
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.logging.slf4j.logback;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
import ch.qos.logback.core.Context;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link StringAppender}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.geode.logging.slf4j.logback.StringAppender
|
||||
* @see ch.qos.logback.classic.Logger
|
||||
* @see ch.qos.logback.core.Appender
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class StringAppenderUnitTests {
|
||||
|
||||
@Mock
|
||||
private StringAppender.StringAppenderWrapper mockWrapper;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).detachAndStopAllAppenders();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildStringAppender() {
|
||||
|
||||
StringAppender stringAppender = new StringAppender.Builder().build();
|
||||
|
||||
assertThat(stringAppender).isNotNull();
|
||||
assertThat(stringAppender.isStarted()).isFalse();
|
||||
assertThat(stringAppender.getContext()).isEqualTo(LoggerFactory.getILoggerFactory());
|
||||
assertThat(stringAppender.getName()).isEqualTo(StringAppender.DEFAULT_NAME);
|
||||
assertThat(stringAppender.getStringAppenderWrapper()).isSameAs(StringAppender.stringBuilderAppenderWrapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildStringAppenderApplyToDelegateUsingReplace() {
|
||||
|
||||
DelegatingAppender delegate = spy(new DelegatingAppender());
|
||||
|
||||
StringAppender stringAppender = new StringAppender.Builder()
|
||||
.applyTo(delegate, true)
|
||||
.build();
|
||||
|
||||
assertThat(stringAppender).isNotNull();
|
||||
assertThat(stringAppender.isStarted()).isFalse();
|
||||
assertThat(stringAppender.getName()).isEqualTo(StringAppender.DEFAULT_NAME);
|
||||
|
||||
verify(delegate, times(1)).setAppender(eq(stringAppender));
|
||||
|
||||
assertThat(delegate.getAppender()).isEqualTo(stringAppender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildAndStartStringAppender() {
|
||||
|
||||
Context mockContext = mock(Context.class);
|
||||
|
||||
DelegatingAppender delegate = spy(new DelegatingAppender());
|
||||
|
||||
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
StringAppender stringAppender = new StringAppender.Builder()
|
||||
.applyTo(delegate)
|
||||
.applyTo(rootLogger)
|
||||
.setContext(mockContext)
|
||||
.setName("TestStringAppender")
|
||||
.useSynchronization()
|
||||
.buildAndStart();
|
||||
|
||||
assertThat(stringAppender).isNotNull();
|
||||
assertThat(stringAppender.isStarted()).isTrue();
|
||||
assertThat(stringAppender.getContext()).isEqualTo(mockContext);
|
||||
assertThat(stringAppender.getName()).isEqualTo("TestStringAppender");
|
||||
assertThat(stringAppender.getStringAppenderWrapper()).isEqualTo(StringAppender.stringBufferAppenderWrapper);
|
||||
assertThat(rootLogger.getAppender("TestStringAppender")).isEqualTo(stringAppender);
|
||||
|
||||
verify(delegate, times(1)).setAppender(isA(CompositeAppender.class));
|
||||
|
||||
Appender compositeAppender = delegate.getAppender();
|
||||
|
||||
assertThat(compositeAppender).isInstanceOf(CompositeAppender.class);
|
||||
assertThat(((CompositeAppender) compositeAppender).getAppenderOne()).isEqualTo(DelegatingAppender.DEFAULT_APPENDER);
|
||||
assertThat(((CompositeAppender) compositeAppender).getAppenderTwo()).isEqualTo(stringAppender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructStringAppender() {
|
||||
|
||||
StringAppender.StringAppenderWrapper mockWrapper = mock(StringAppender.StringAppenderWrapper.class);
|
||||
|
||||
StringAppender appender = new StringAppender(mockWrapper);
|
||||
|
||||
assertThat(appender).isNotNull();
|
||||
assertThat(appender.getStringAppenderWrapper()).isEqualTo(mockWrapper);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructStringAppenderWithNullWrapper() {
|
||||
|
||||
try {
|
||||
new StringAppender(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("StringAppenderWrapper must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendCallsConfiguredStringAppenderWrapper() {
|
||||
|
||||
ILoggingEvent mockEvent = mock(ILoggingEvent.class);
|
||||
|
||||
StringAppender appender = spy(new StringAppender(this.mockWrapper));
|
||||
|
||||
doReturn(this.mockWrapper).when(appender).getStringAppenderWrapper();
|
||||
doReturn("TEST").when(appender).toString(eq(mockEvent));
|
||||
|
||||
appender.append(mockEvent);
|
||||
|
||||
verify(this.mockWrapper, times(1)).append(eq("TEST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIgnoresBlankEmptyAndNullStrings() {
|
||||
|
||||
ILoggingEvent mockEvent = mock(ILoggingEvent.class);
|
||||
|
||||
StringAppender appender = spy(new StringAppender(this.mockWrapper));
|
||||
|
||||
doReturn(this.mockWrapper).when(appender).getStringAppenderWrapper();
|
||||
doReturn(" ").doReturn("").doReturn(null)
|
||||
.when(appender).toString(eq(mockEvent));
|
||||
|
||||
appender.append(mockEvent);
|
||||
appender.append(mockEvent);
|
||||
appender.append(mockEvent);
|
||||
|
||||
verify(appender, times(3)).toString(eq(mockEvent));
|
||||
verify(appender, times(1)).preProcessLogMessage(eq(" "));
|
||||
verify(appender, times(1)).preProcessLogMessage(eq(""));
|
||||
verify(appender, times(1)).preProcessLogMessage(eq(null));
|
||||
verify(this.mockWrapper, never()).append(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendIsNullSafe() {
|
||||
|
||||
StringAppender appender = spy(new StringAppender(this.mockWrapper));
|
||||
|
||||
doReturn(this.mockWrapper).when(appender).getStringAppenderWrapper();
|
||||
|
||||
appender.append(null);
|
||||
|
||||
verify(appender, never()).toString(any(ILoggingEvent.class));
|
||||
verify(this.mockWrapper, never()).append(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyStringIsNotValidLogMessage() {
|
||||
|
||||
StringAppender appender = new StringAppender(this.mockWrapper);
|
||||
|
||||
assertThat(appender.isValidLogMessage("")).isFalse();
|
||||
assertThat(appender.isValidLogMessage(null)).isFalse(); }
|
||||
|
||||
@Test
|
||||
public void nonEmptyStringIsValidLogMessage() {
|
||||
|
||||
StringAppender appender = new StringAppender(this.mockWrapper);
|
||||
|
||||
assertThat(appender.isValidLogMessage("TEST")).isTrue();
|
||||
assertThat(appender.isValidLogMessage("_")).isTrue();
|
||||
assertThat(appender.isValidLogMessage(" ")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preProcessLogMessageIsNullSafe() {
|
||||
assertThat(new StringAppender(this.mockWrapper).preProcessLogMessage(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preProcessLogMessageTrimsMessage() {
|
||||
|
||||
StringAppender appender = new StringAppender(this.mockWrapper);
|
||||
|
||||
assertThat(appender.preProcessLogMessage("TEST")).isEqualTo("TEST");
|
||||
assertThat(appender.preProcessLogMessage(" MOCK ")).isEqualTo("MOCK");
|
||||
assertThat(appender.preProcessLogMessage("J UNK ")).isEqualTo("J UNK");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringCallsLoggingEventFormattedMessage() {
|
||||
|
||||
ILoggingEvent mockEvent = mock(ILoggingEvent.class);
|
||||
|
||||
when(mockEvent.getFormattedMessage()).thenReturn("TEST");
|
||||
|
||||
assertThat(new StringAppender(this.mockWrapper).toString(mockEvent)).isEqualTo("TEST");
|
||||
|
||||
verify(mockEvent, times(1)).getFormattedMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringIsNullSafe() {
|
||||
assertThat(new StringAppender(this.mockWrapper).toString(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLogOutputCallsStringAppenderWrapperToString() {
|
||||
|
||||
doReturn("TEST").when(this.mockWrapper).toString();
|
||||
|
||||
assertThat(new StringAppender(this.mockWrapper).getLogOutput()).isEqualTo("TEST");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user