diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1eeeb0c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# Created by .ignore support plugin (hsz.mobi)
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+.idea
+*.iml
+
+
+### Maven template
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+
+# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
+!/.mvn/wrapper/maven-wrapper.jar
+
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..f5c99a7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1 @@
+language: java
\ No newline at end of file
diff --git a/java/logback-spike/LICENSE b/LICENSE
similarity index 83%
rename from java/logback-spike/LICENSE
rename to LICENSE
index f4a67ed..2625adb 100644
--- a/java/logback-spike/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2016 Patrick Kua
+Copyright for portions of this project are held by Patrick Kua, 2016 as part of project thekua/Sample-Code. All other copyright for project schnatterer/logback-spike are held by Johannes Schnatterer, 2017.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a2feddc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,47 @@
+# logback-spike
+[](https://travis-ci.org/schnatterer/logback-spike)
+[](https://jitpack.io/#schnatterer/logback-spike)
+[](LICENSE)
+
+Logback and SLF4j unit testing.
+
+Original idea from [thekua's blog](https://www.thekua.com/atwork/2011/11/testing-logging-with-logback/), forked from [his repo](https://github.com/thekua/Sample-Code/tree/master/java/logback-spike) in order to provide it conveniently with good reuse as maven dependency.
+
+## Usage
+
+Get it via [JitPack](https://jitpack.io/#schnatterer/logback-spike), for example using maven.
+
+Add the following maven repository to your POM.xml
+
+```xml
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+```
+
+Then add the actual dependency
+
+```xml
+
+ com.github.schnatterer
+ logback-spike
+ 1.0.0
+ test
+
+```
+
+From here it's really simple to use:
+````java
+// Given
+LogbackCapturingAppender capturing = LogbackCapturingAppender.weaveInto(OurDomainWithLogger.LOG);
+
+// when
+new OurDomainWithLogger().logInfo("This should be logged{}", "!");
+
+// then
+assertThat(capturing.getCapturedLogMessages().get(0), is("This should be logged!"));
+````
+See [LogbackCapturingAppender's javadoc](src/main/java/com/thekua/spikes/LogbackCapturingAppender.java) and [its unit test](src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java) for more insights.
diff --git a/java/.gitignore b/java/.gitignore
deleted file mode 100644
index 7df3665..0000000
--- a/java/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.class
-*.ipr
-*.iws
-*.iml
-target
diff --git a/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppender.java b/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppender.java
deleted file mode 100644
index 9af6810..0000000
--- a/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppender.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.thekua.spikes;
-
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
-import ch.qos.logback.core.AppenderBase;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class LogbackCapturingAppender extends AppenderBase {
- public static class Factory {
- private static List ALL = new ArrayList();
-
- public static LogbackCapturingAppender weaveInto(org.slf4j.Logger sl4jLogger) {
- LogbackCapturingAppender appender = new LogbackCapturingAppender(sl4jLogger);
- ALL.add(appender);
- return appender;
- }
-
-
- public static void cleanUp() {
- for (LogbackCapturingAppender appender : ALL) {
- appender.cleanUp();
- }
- }
-
- }
-
- private final Logger logger;
- private ILoggingEvent captured;
-
- public LogbackCapturingAppender(org.slf4j.Logger sl4jLogger) {
- this.logger = (Logger) sl4jLogger;
- connect(logger);
- detachDefaultConsoleAppender();
- }
-
- private void detachDefaultConsoleAppender() {
- Logger rootLogger = getRootLogger();
- Appender consoleAppender = rootLogger.getAppender("console");
- rootLogger.detachAppender(consoleAppender);
- }
-
- private Logger getRootLogger() {
- return logger.getLoggerContext().getLogger("ROOT");
- }
-
- private void connect(Logger logger) {
- logger.setLevel(Level.ALL);
- logger.addAppender(this);
- this.start();
- }
-
- public String getCapturedLogMessage() {
- return captured.getMessage();
- }
-
- @Override
- protected void append(ILoggingEvent iLoggingEvent) {
- captured = iLoggingEvent;
- }
-
- private void cleanUp() {
- logger.detachAppender(this);
-
- }
-}
diff --git a/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java b/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java
deleted file mode 100644
index 45b1d6b..0000000
--- a/java/logback-spike/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.thekua.spikes;
-
-
-import org.junit.After;
-import org.junit.Test;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-
-public class LogbackCapturingAppenderTest {
- @After
- public void cleanUp() {
- LogbackCapturingAppender.Factory.cleanUp();
- }
-
- @Test
- public void shouldCaptureAGivenLog() throws Exception {
- // Given
- LogbackCapturingAppender capturing = LogbackCapturingAppender.Factory.weaveInto(OurDomainWithLogger.LOG);
- OurDomainWithLogger domainClass = new OurDomainWithLogger();
-
- // when
- domainClass.logThis("This should be logged");
-
- // then
- assertThat(capturing.getCapturedLogMessage(), is("This should be logged"));
- }
-
- @Test
- public void shouldNotCaptureAGiveLogAfterCleanUp() throws Exception {
- // Given
- LogbackCapturingAppender capturing = LogbackCapturingAppender.Factory.weaveInto(OurDomainWithLogger.LOG);
- OurDomainWithLogger domainClass = new OurDomainWithLogger();
- domainClass.logThis("This should be logged at info");
- LogbackCapturingAppender.Factory.cleanUp();
-
- // when
- domainClass.logThis("This should not be logged");
-
- // then
- assertThat(capturing.getCapturedLogMessage(), is("This should be logged at info"));
- }
-}
diff --git a/java/logback-spike/pom.xml b/pom.xml
similarity index 54%
rename from java/logback-spike/pom.xml
rename to pom.xml
index f32f7fc..c63d9c4 100644
--- a/java/logback-spike/pom.xml
+++ b/pom.xml
@@ -1,40 +1,41 @@
-
+
4.0.0
com.thekua.spikes
logback-spike
- 1.0-SNAPSHOT
+ 1.0.1-SNAPSHOT
jar
logback-spike
- http://maven.apache.org
UTF-8
+
+ scm:git:git@github.com:schnatterer/logback-spike.git
+ scm:git:git@github.com:schnatterer/logback-spike.git
+ https://github.com/schnatterer/logback-spike
+ HEAD
+
+
-
- org.slf4j
- slf4j-api
- 1.6.2
-
ch.qos.logback
logback-classic
- 1.0.0
+ 1.2.3
junit
- junit-dep
- 4.8.2
+ junit
+ 4.12
test
org.hamcrest
hamcrest-all
- 1.2
+ 1.3
+ test
diff --git a/src/main/java/com/thekua/spikes/LogbackCapturingAppender.java b/src/main/java/com/thekua/spikes/LogbackCapturingAppender.java
new file mode 100644
index 0000000..f7270ab
--- /dev/null
+++ b/src/main/java/com/thekua/spikes/LogbackCapturingAppender.java
@@ -0,0 +1,100 @@
+package com.thekua.spikes;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.AppenderBase;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Logback appender that simply stores all logged messages of an {@link org.slf4j.Logger} in memory and provides methods
+ * to retrieve them, so they can be used in asserts of unit tests.
+ *
+ * Add a logger like so
+ * {@code LogbackCapturingAppender capturing = LogbackCapturingAppender.weaveInto(OurDomainWithLogger.LOG); }
+ *
+ * Retrieve any log messages using any of the following methods:
+ *
+ * - {@link #getCapturedEvents()}
+ * - {@link #getCapturedLogMessages()}
+ *
+ *
+ * If necessary remove appender instance or all {@link LogbackCapturingAppender}s using
+ *
+ *
+ * - {@link #cleanUp()}
+ * - {@link #cleanUpAll()}
+ *
+ */
+public class LogbackCapturingAppender extends AppenderBase {
+ private static final List ALL = new ArrayList();
+
+ private final Logger logger;
+
+ private List capturedEvents = new LinkedList();
+
+ public static LogbackCapturingAppender weaveInto(org.slf4j.Logger sl4jLogger) {
+ LogbackCapturingAppender appender = new LogbackCapturingAppender(sl4jLogger);
+ ALL.add(appender);
+ return appender;
+ }
+
+ public static void cleanUpAll() {
+ for (LogbackCapturingAppender appender : ALL) {
+ appender.cleanUp();
+ }
+ }
+
+ public void cleanUp() {
+ logger.detachAppender(this);
+ }
+
+ /**
+ * @return whole event, including log level, unformatted message, etc.
+ */
+ public List getCapturedEvents() {
+ return capturedEvents;
+ }
+
+ /**
+ * @return formatted message strings
+ */
+ public List getCapturedLogMessages() {
+ List capturedMessages = new LinkedList();
+ for (ILoggingEvent capturedEvent : capturedEvents) {
+ capturedMessages.add(capturedEvent.getFormattedMessage());
+ }
+ return capturedMessages;
+ }
+
+ @Override
+ protected void append(ILoggingEvent iLoggingEvent) {
+ capturedEvents.add(iLoggingEvent);
+ }
+
+ private LogbackCapturingAppender(org.slf4j.Logger sl4jLogger) {
+ this.logger = (Logger) sl4jLogger;
+ connect(logger);
+ detachDefaultConsoleAppender();
+ }
+
+ private void detachDefaultConsoleAppender() {
+ Logger rootLogger = getRootLogger();
+ Appender consoleAppender = rootLogger.getAppender("console");
+ rootLogger.detachAppender(consoleAppender);
+ }
+
+ private Logger getRootLogger() {
+ return logger.getLoggerContext().getLogger("ROOT");
+ }
+
+ private void connect(Logger logger) {
+ logger.setLevel(Level.ALL);
+ logger.addAppender(this);
+ this.start();
+ }
+}
diff --git a/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java b/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java
new file mode 100644
index 0000000..0e7510f
--- /dev/null
+++ b/src/test/java/com/thekua/spikes/LogbackCapturingAppenderTest.java
@@ -0,0 +1,76 @@
+package com.thekua.spikes;
+
+
+import ch.qos.logback.classic.Level;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class LogbackCapturingAppenderTest {
+ @After
+ public void cleanUp() {
+ LogbackCapturingAppender.cleanUpAll();
+ }
+
+ @Test
+ public void shouldCaptureAGivenLogMessage() throws Exception {
+ // Given
+ LogbackCapturingAppender capturing = LogbackCapturingAppender.weaveInto(OurDomainWithLogger.LOG);
+ OurDomainWithLogger domainClass = new OurDomainWithLogger();
+
+ // when
+ domainClass.logInfo("This should be logged{}", "!");
+
+ // then
+ assertThat(capturing.getCapturedLogMessages().get(0), is("This should be logged!"));
+ }
+
+ @Test
+ public void shouldCaptureMultipleLogMessages() throws Exception {
+ // Given, when
+ LogbackCapturingAppender capturing = sendMultipleFormattedMessages();
+
+ // then
+ assertThat(capturing.getCapturedLogMessages().get(0), is("This should be logged!"));
+ assertThat(capturing.getCapturedLogMessages().get(1), is("This should also be logged"));
+ }
+
+ @Test
+ public void shouldCaptureMultipleLogEvents() throws Exception {
+ LogbackCapturingAppender capturing = sendMultipleFormattedMessages();
+
+ // then
+ assertThat(capturing.getCapturedEvents().get(0).getLevel(), is(Level.INFO));
+ assertThat(capturing.getCapturedEvents().get(1).getLevel(), is(Level.WARN));
+ }
+
+
+ @Test
+ public void shouldNotCaptureAGiveLogAfterCleanUp() throws Exception {
+ // Given
+ LogbackCapturingAppender capturing = LogbackCapturingAppender.weaveInto(OurDomainWithLogger.LOG);
+ OurDomainWithLogger domainClass = new OurDomainWithLogger();
+ domainClass.logInfo("This should be logged at info");
+ LogbackCapturingAppender.cleanUpAll();
+
+ // when
+ domainClass.logInfo("This should not be logged");
+
+ // then
+ assertThat(capturing.getCapturedLogMessages().get(0), is("This should be logged at info"));
+ }
+
+ private LogbackCapturingAppender sendMultipleFormattedMessages() {
+ // Given
+ LogbackCapturingAppender capturing = LogbackCapturingAppender.weaveInto(OurDomainWithLogger.LOG);
+ OurDomainWithLogger domainClass = new OurDomainWithLogger();
+
+ // when
+ domainClass.logInfo("This should be logged{}", "!");
+ domainClass.logWarn("This should also be logged");
+ return capturing;
+ }
+
+}
diff --git a/java/logback-spike/src/main/java/com/thekua/spikes/OurDomainWithLogger.java b/src/test/java/com/thekua/spikes/OurDomainWithLogger.java
similarity index 52%
rename from java/logback-spike/src/main/java/com/thekua/spikes/OurDomainWithLogger.java
rename to src/test/java/com/thekua/spikes/OurDomainWithLogger.java
index 785ac6b..6d52f76 100644
--- a/java/logback-spike/src/main/java/com/thekua/spikes/OurDomainWithLogger.java
+++ b/src/test/java/com/thekua/spikes/OurDomainWithLogger.java
@@ -8,8 +8,16 @@ public class OurDomainWithLogger {
static Logger LOG = LoggerFactory.getLogger(OurDomainWithLogger.class);
- public void logThis(String message) {
+ public void logInfo(String message) {
LOG.info(message);
}
+ public void logWarn(String message) {
+ LOG.warn(message);
+ }
+
+ public void logInfo(String message, Object... args) {
+ LOG.info(message, args);
+ }
+
}