diff --git a/commons-logging/pom.xml b/commons-logging/pom.xml index ce1a59e..3f59449 100644 --- a/commons-logging/pom.xml +++ b/commons-logging/pom.xml @@ -28,7 +28,7 @@ commons-logging commons-logging provided - 1.3.4 + ${commons-logging.version} hamcrest @@ -66,6 +66,22 @@ 1.1.0-SNAPSHOT + + + + + maven-javadoc-plugin + + + https://javadoc.io/doc/commons-logging/commons-logging/${commons-logging.version} + + + org.apache.maven.plugins + + + + release + @@ -78,4 +94,7 @@ run-its + + 1.3.4 + diff --git a/commons-logging/readme.md b/commons-logging/readme.md index 5437da8..dc71480 100644 --- a/commons-logging/readme.md +++ b/commons-logging/readme.md @@ -20,7 +20,7 @@ Just put a test dependency to your POM: mock-loggers-commons-logging io.github.vitalijr2.logging test - 1.0.0 + 1.1.0 ``` diff --git a/commons-logging/src/it/hello-commons-logging-world/pom.xml b/commons-logging/src/it/hello-commons-logging-world/pom.xml index a77f291..da491b4 100644 --- a/commons-logging/src/it/hello-commons-logging-world/pom.xml +++ b/commons-logging/src/it/hello-commons-logging-world/pom.xml @@ -28,31 +28,23 @@ - - - commons-logging - commons-logging - 1.3.4 - - @project.artifactId@ @project.groupId@ test @project.version@ + + commons-logging + commons-logging + 1.3.4 + hamcrest org.hamcrest test 3.0 - - junit-jupiter-api - org.junit.jupiter - test - ${junit-jupiter.version} - junit-jupiter-engine org.junit.jupiter diff --git a/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/MockLoggerFactory.java b/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/MockLoggerFactory.java index 7c7178e..adc0b0f 100644 --- a/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/MockLoggerFactory.java +++ b/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/MockLoggerFactory.java @@ -34,7 +34,7 @@ import org.jetbrains.annotations.VisibleForTesting; /** - * Uses {@link org.mockito.Mockito#mock(Class, String)} to get a mock that is adapted for {@link System.Logger}. + * Uses {@link org.mockito.Mockito#mock(Class, String)} to get a mock that is adapted for {@link Log}. *

* Example: *


diff --git a/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/package-info.java b/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/package-info.java
index 00a21b2..f96d116 100644
--- a/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/package-info.java
+++ b/commons-logging/src/main/java/io/github/vitalijr2/logging/mock/commons/package-info.java
@@ -1,5 +1,6 @@
 /**
- * Mock loggers for Apache Commons Logging backed by Mockito.
+ * Mock loggers for Apache Commons Logging backed by Mockito.
  *
  * @since 1.0.0
  */
diff --git a/jdk-platform-logging/readme.md b/jdk-platform-logging/readme.md
index 8c58d13..1ddfe4b 100644
--- a/jdk-platform-logging/readme.md
+++ b/jdk-platform-logging/readme.md
@@ -19,7 +19,7 @@ Just put a test dependency to your POM:
     mock-loggers-jdk-platform-logging
     io.github.vitalijr2.logging
     test
-    1.0.0
+    1.1.0
 
 ```
 
diff --git a/jdk-platform-logging/src/it/hello-jdk-platform-logging-world/pom.xml b/jdk-platform-logging/src/it/hello-jdk-platform-logging-world/pom.xml
index ebcc0be..2be8443 100644
--- a/jdk-platform-logging/src/it/hello-jdk-platform-logging-world/pom.xml
+++ b/jdk-platform-logging/src/it/hello-jdk-platform-logging-world/pom.xml
@@ -28,7 +28,6 @@
     
   
   
-    
     
       @project.artifactId@
       @project.groupId@
@@ -41,12 +40,6 @@
       test
       3.0
     
-    
-      junit-jupiter-api
-      org.junit.jupiter
-      test
-      ${junit-jupiter.version}
-    
     
       junit-jupiter-engine
       org.junit.jupiter
diff --git a/jdk-platform-logging/src/main/java/io/github/vitalijr2/logging/mock/platform/package-info.java b/jdk-platform-logging/src/main/java/io/github/vitalijr2/logging/mock/platform/package-info.java
index 6a8debd..3570d73 100644
--- a/jdk-platform-logging/src/main/java/io/github/vitalijr2/logging/mock/platform/package-info.java
+++ b/jdk-platform-logging/src/main/java/io/github/vitalijr2/logging/mock/platform/package-info.java
@@ -1,5 +1,6 @@
 /**
- * Mock loggers for JDK Platform Logging backed by Mockito.
+ * Mock loggers for JDK Platform Logging backed by Mockito.
  *
  * @since 1.0.0
  */
diff --git a/readme.md b/readme.md
index b6fb2c9..3801fb1 100644
--- a/readme.md
+++ b/readme.md
@@ -30,13 +30,14 @@ void helloWorld() {
 ```
 
 Now this library implements services for [JDK Platform Logging][jdk-logging],
-[Apache Commons Logging][commons-logging] and [SLF4J][slf4j].
+[Apache Commons Logging][commons-logging], [SLF4J][slf4j] and [tinylog][].
 
 See more examples in the relevant modules of this project:
 
 - for Apache Commons Logging in [mock-loggers-commons-logging](commons-logging)
 - for JDK Platform Logging in [mock-loggers-jdk-platform-logging](jdk-platform-logging)
 - for SLF4J in [mock-loggers-slf4j](slf4j)
+- for tinylog in [mock-loggers-tinylog-provider](tinylog-provider)
 
 ## Other logging libraries and frameworks
 
@@ -86,6 +87,8 @@ See full text [here](LICENSE "the LICENSE file").
 
 [slf4j]: https://www.slf4j.org/
 
+[tinylog]: https://tinylog.org/v2/
+
 [java-version]: https://img.shields.io/static/v1?label=Java&message=11&color=blue&logoColor=E23D28
 
 [jdk-download]: https://www.oracle.com/java/technologies/downloads/#java11
diff --git a/slf4j/pom.xml b/slf4j/pom.xml
index f5f5856..d1036b5 100644
--- a/slf4j/pom.xml
+++ b/slf4j/pom.xml
@@ -54,7 +54,7 @@
       slf4j-api
       org.slf4j
       provided
-      2.0.16
+      ${slf4j.version}
     
   
   Mock loggers for SLF4J backed by Mockito.
@@ -66,6 +66,22 @@
     1.1.0-SNAPSHOT
   
   
+    
+      
+        
+          
+            maven-javadoc-plugin
+            
+              
+                https://javadoc.io/doc/org.slf4j/slf4j-api/${slf4j.version}
+              
+            
+            org.apache.maven.plugins
+          
+        
+      
+      release
+    
     
       
         
@@ -78,4 +94,7 @@
       run-its
     
   
+  
+    2.0.16
+  
 
diff --git a/slf4j/readme.md b/slf4j/readme.md
index 4f03b1b..1644ffc 100644
--- a/slf4j/readme.md
+++ b/slf4j/readme.md
@@ -20,7 +20,7 @@ Just put a test dependency to your POM:
     mock-loggers-slf4j
     io.github.vitalijr2.logging
     test
-    1.0.0
+    1.1.0
 
 ```
 
diff --git a/slf4j/src/it/hello-slf4j-world/pom.xml b/slf4j/src/it/hello-slf4j-world/pom.xml
index cae231f..60d995d 100644
--- a/slf4j/src/it/hello-slf4j-world/pom.xml
+++ b/slf4j/src/it/hello-slf4j-world/pom.xml
@@ -28,13 +28,6 @@
     
   
   
-    
-    
-      slf4j-api
-      org.slf4j
-      2.0.16
-    
-    
     
       @project.artifactId@
       @project.groupId@
@@ -47,12 +40,6 @@
       test
       3.0
     
-    
-      junit-jupiter-api
-      org.junit.jupiter
-      test
-      ${junit-jupiter.version}
-    
     
       junit-jupiter-engine
       org.junit.jupiter
@@ -77,6 +64,11 @@
       test
       ${mockito.version}
     
+    
+      slf4j-api
+      org.slf4j
+      2.0.16
+    
   
   Basic example
   example.hello
diff --git a/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/MockLoggerFactory.java b/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/MockLoggerFactory.java
index fe32191..cca0f43 100644
--- a/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/MockLoggerFactory.java
+++ b/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/MockLoggerFactory.java
@@ -33,7 +33,7 @@
 import org.slf4j.Logger;
 
 /**
- * Uses {@link org.mockito.Mockito#mock(Class, String)} to get a mock that is adapted for {@link System.Logger}.
+ * Uses {@link org.mockito.Mockito#mock(Class, String)} to get a mock that is adapted for {@link Logger}.
  * 

* Example: *


diff --git a/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/package-info.java b/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/package-info.java
index 2acad17..7223e41 100644
--- a/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/package-info.java
+++ b/slf4j/src/main/java/io/github/vitalijr2/logging/mock/slf4j/package-info.java
@@ -1,5 +1,6 @@
 /**
- * Mock loggers for SLF4J backed by Mockito.
+ * Mock loggers for SLF4J backed by Mockito.
  *
  * @since 1.0.0
  */
diff --git a/tinylog-provider/pom.xml b/tinylog-provider/pom.xml
index ece7927..09d2284 100644
--- a/tinylog-provider/pom.xml
+++ b/tinylog-provider/pom.xml
@@ -64,7 +64,7 @@
       tinylog-api
       org.tinylog
       provided
-      2.7.0
+      ${tinylog.version}
     
   
   Mock loggers for tinylog backed by Mockito.
@@ -76,6 +76,22 @@
     1.1.0-SNAPSHOT
   
   
+    
+      
+        
+          
+            maven-javadoc-plugin
+            
+              
+                https://javadoc.io/doc/org.tinylog/tinylog-api/${tinylog.version}
+              
+            
+            org.apache.maven.plugins
+          
+        
+      
+      release
+    
     
       
         
@@ -88,4 +104,7 @@
       run-its
     
   
+  
+    2.7.0
+  
 
diff --git a/tinylog-provider/readme.md b/tinylog-provider/readme.md
new file mode 100644
index 0000000..d5ff7ed
--- /dev/null
+++ b/tinylog-provider/readme.md
@@ -0,0 +1,149 @@
+# Mock loggers for tinylog
+
+[Tinylog][tinylog] provider with a mock instance backed by [Mockito][].
+
+> [!WARNING]
+> This library does not support _parallel test execution_.
+
+[![Java Version][java-version]][jdk-download]
+![Tinylog Version][tinylog-version]
+![Mockito Version][mockito-version]  
+![Maven Central Last Update][maven-central-last-update]
+[![Maven Central][maven-central]][maven-central-link]
+[![Javadoc][javadoc]][javadoc-link]
+
+## How to use
+
+Just put a test dependency to your POM:
+```xml
+
+    mock-loggers-tinylog-provider
+    io.github.vitalijr2.logging
+    test
+    1.1.0
+
+```
+
+The simplest usage example looks like this:
+```java
+@Test
+void helloWorld() {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(helloService::sayHelloWorld);
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(), anyString(), isNull());
+}
+```
+See more details at [HelloServiceBasicTest.java](src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceBasicTest.java)
+
+> [!IMPORTANT]
+> Keep in mind that all loggers are initialized only once during the test run.
+
+Therefore, a more complex example cleans the loggers after (or before) each test:
+```java
+// the static logger instance
+@MockTinylogProvider
+private static LoggingProvider logger;
+
+// clean the mock logger after each test
+@AfterEach
+void tearDown() {
+    clearInvocations(logger);
+}
+
+// use the mock logger in a test
+@DisplayName("Names")
+@ParameterizedTest(name = "<{0}>")
+@ValueSource(strings = {"John", "Jane"})
+void names(String name) {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(() -> helloService.sayHello(name));
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+            eq("Hello " + name + "!"), isNull());
+}
+```
+See more details at [HelloServiceFullTest.java](src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceFullTest.java)
+
+To avoid manual cleaning of mock loggers you can use the [jUnit extension][junit-extension] for automation.
+
+```java
+@ExtendWith(MockLoggerExtension.class)
+class HelloServiceExtensionTest {
+
+    @MockTinylogProvider
+    private static LoggingProvider logger;
+
+    @DisplayName("Names")
+    @ParameterizedTest(name = "<{0}>")
+    @ValueSource(strings = {"John", "Jane"})
+    void names(String name) {
+        when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+        var helloService = new HelloService();
+
+        assertDoesNotThrow(() -> helloService.sayHello(name));
+
+        verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+                eq("Hello " + name + "!"), isNull());
+    }
+
+}
+```
+See more details at [HelloServiceExtensionTest.java](src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceExtensionTest.java)
+
+Also you can use the annotation for automation.
+```java
+@MockLoggers
+class HelloServiceAnnotationTest {
+
+    @MockTinylogProvider
+    private static LoggingProvider logger;
+
+    @DisplayName("Names")
+    @ParameterizedTest(name = "<{0}>")
+    @ValueSource(strings = {"John", "Jane"})
+    void names(String name) {
+        when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+        var helloService = new HelloService();
+
+        assertDoesNotThrow(() -> helloService.sayHello(name));
+
+        verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+                eq("Hello " + name + "!"), isNull());
+    }
+
+}
+```
+See more details at [HelloServiceAnnotationTest.java](src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceAnnotationTest.java)
+
+[tinylog]: https://tinylog.org/v2/
+
+[Mockito]: https://site.mockito.org
+
+[java-version]: https://img.shields.io/static/v1?label=Java&message=11&color=blue&logoColor=E23D28
+
+[jdk-download]: https://www.oracle.com/java/technologies/downloads/#java11
+
+[tinylog-version]: https://img.shields.io/static/v1?label=tinylog&message=2.7.0&color=blue&logoColor=E23D28
+
+[mockito-version]: https://img.shields.io/static/v1?label=Mockito&message=5.14.2&color=blue&logoColor=E23D28
+
+[maven-central-last-update]: https://img.shields.io/maven-central/last-update/io.github.vitalijr2.logging/mock-loggers-tinylog-provider
+
+[maven-central]: https://img.shields.io/maven-central/v/io.github.vitalijr2.logging/mock-loggers-tinylog-provider
+
+[maven-central-link]: https://central.sonatype.com/artifact/io.github.vitalijr2.logging/mock-loggers-tinylog-provider?smo=true
+
+[javadoc]: https://javadoc.io/badge2/io.github.vitalijr2.logging/mock-loggers-tinylog-provider/javadoc.svg
+
+[javadoc-link]: https://javadoc.io/doc/io.github.vitalijr2.logging/mock-loggers-tinylog-provider
+
+[junit-extension]: ../core/
diff --git a/tinylog-provider/src/it/hello-tinylog-world/extension-logging.properties b/tinylog-provider/src/it/hello-tinylog-world/extension-logging.properties
new file mode 100644
index 0000000..cd35a2c
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/extension-logging.properties
@@ -0,0 +1,8 @@
+.level = INFO
+
+handlers = java.util.logging.ConsoleHandler
+
+java.util.logging.ConsoleHandler.level = ALL
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+io.github.vitalijr2.mock.jdk.platform.logging.MockLoggerExtension.level = FINE
diff --git a/tinylog-provider/src/it/hello-tinylog-world/pom.xml b/tinylog-provider/src/it/hello-tinylog-world/pom.xml
new file mode 100644
index 0000000..f62dffd
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/pom.xml
@@ -0,0 +1,83 @@
+
+
+  hello-tinylog-world
+  
+    
+      
+        maven-compiler-plugin
+        
+          ${java.version}
+          ${java.version}
+          ${java.version}
+        
+        org.apache.maven.plugins
+        3.13.0
+      
+      
+        maven-surefire-plugin
+        
+          
+            extension-logging.properties
+          
+        
+        org.apache.maven.plugins
+        3.5.2
+      
+    
+  
+  
+    
+      @project.artifactId@
+      @project.groupId@
+      test
+      @project.version@
+    
+    
+      hamcrest
+      org.hamcrest
+      test
+      3.0
+    
+    
+      junit-jupiter-engine
+      org.junit.jupiter
+      test
+      ${junit-jupiter.version}
+    
+    
+      junit-jupiter-params
+      org.junit.jupiter
+      test
+      ${junit-jupiter.version}
+    
+    
+      mockito-core
+      org.mockito
+      test
+      ${mockito.version}
+    
+    
+      mockito-junit-jupiter
+      org.mockito
+      test
+      ${mockito.version}
+    
+    
+      tinylog-api
+      org.tinylog
+      2.7.0
+    
+  
+  Basic example
+  example.hello
+  4.0.0
+  
+    11
+    5.11.3
+    5.14.2
+    UTF-8
+  
+  1.0.0
+
diff --git a/tinylog-provider/src/it/hello-tinylog-world/src/main/java/example/hello/HelloService.java b/tinylog-provider/src/it/hello-tinylog-world/src/main/java/example/hello/HelloService.java
new file mode 100644
index 0000000..b0c04c4
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/src/main/java/example/hello/HelloService.java
@@ -0,0 +1,25 @@
+package example.hello;
+
+import static java.util.Objects.requireNonNull;
+
+import org.tinylog.Logger;
+
+public class HelloService {
+
+  public String sayHelloWorld() {
+    return sayHello("World");
+  }
+
+  public String sayHello(String name) {
+    if (requireNonNull(name, "Name is missed").isBlank()) {
+      throw new IllegalArgumentException("Name is empty");
+    }
+
+    var greeting = "Hello " + name + "!";
+
+    Logger.info(greeting);
+
+    return greeting;
+  }
+
+}
diff --git a/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceAnnotationTest.java b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceAnnotationTest.java
new file mode 100644
index 0000000..a2b5dce
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceAnnotationTest.java
@@ -0,0 +1,41 @@
+package example.hello;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.github.vitalijr2.logging.mock.MockLoggers;
+import io.github.vitalijr2.logging.mock.tinylog.MockTinylogProvider;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.tinylog.Level;
+import org.tinylog.provider.LoggingProvider;
+
+@MockLoggers
+class HelloServiceAnnotationTest {
+
+  @MockTinylogProvider
+  private static LoggingProvider logger;
+
+  @BeforeEach
+  void setUp() {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+  }
+
+  @DisplayName("Names")
+  @ParameterizedTest(name = "<{0}>")
+  @ValueSource(strings = {"John", "Jane"})
+  void names(String name) {
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(() -> helloService.sayHello(name));
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+        eq("Hello " + name + "!"), isNull());
+  }
+
+}
diff --git a/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceBasicTest.java b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceBasicTest.java
new file mode 100644
index 0000000..9418b98
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceBasicTest.java
@@ -0,0 +1,33 @@
+package example.hello;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.github.vitalijr2.logging.mock.tinylog.MockTinylogProvider;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.tinylog.Level;
+import org.tinylog.provider.LoggingProvider;
+
+class HelloServiceBasicTest {
+
+  @MockTinylogProvider
+  private static LoggingProvider logger;
+
+  @DisplayName("Hello world")
+  @Test
+  void helloWorld() {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(helloService::sayHelloWorld);
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(), anyString(), isNull());
+  }
+
+}
diff --git a/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceExtensionTest.java b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceExtensionTest.java
new file mode 100644
index 0000000..89fe29e
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceExtensionTest.java
@@ -0,0 +1,42 @@
+package example.hello;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.github.vitalijr2.logging.mock.MockLoggerExtension;
+import io.github.vitalijr2.logging.mock.tinylog.MockTinylogProvider;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.tinylog.Level;
+import org.tinylog.provider.LoggingProvider;
+
+@ExtendWith(MockLoggerExtension.class)
+class HelloServiceExtensionTest {
+
+  @MockTinylogProvider
+  private static LoggingProvider logger;
+
+  @BeforeEach
+  void setUp() {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+  }
+
+  @DisplayName("Names")
+  @ParameterizedTest(name = "<{0}>")
+  @ValueSource(strings = {"John", "Jane"})
+  void names(String name) {
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(() -> helloService.sayHello(name));
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+        eq("Hello " + name + "!"), isNull());
+  }
+
+}
diff --git a/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceFullTest.java b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceFullTest.java
new file mode 100644
index 0000000..76c7228
--- /dev/null
+++ b/tinylog-provider/src/it/hello-tinylog-world/src/test/java/example/hello/HelloServiceFullTest.java
@@ -0,0 +1,63 @@
+package example.hello;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringStartsWith.startsWith;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+import io.github.vitalijr2.logging.mock.tinylog.MockTinylogProvider;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.tinylog.Level;
+import org.tinylog.provider.LoggingProvider;
+
+class HelloServiceFullTest {
+
+  @MockTinylogProvider
+  private static LoggingProvider logger;
+
+  @BeforeEach
+  void setUp() {
+    clearInvocations(logger);
+    reset(logger);
+  }
+
+  @DisplayName("Names")
+  @ParameterizedTest(name = "<{0}>")
+  @ValueSource(strings = {"John", "Jane"})
+  void names(String name) {
+    when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+
+    var helloService = new HelloService();
+
+    assertDoesNotThrow(() -> helloService.sayHello(name));
+
+    verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(),
+        eq("Hello " + name + "!"), isNull());
+  }
+
+  @DisplayName("Null or empty name")
+  @ParameterizedTest(name = "<{0}>")
+  @NullAndEmptySource
+  @ValueSource(strings = "   ")
+  void nullOrEmptyName(String name) {
+    var helloService = new HelloService();
+
+    var exception = assertThrows(RuntimeException.class, () -> helloService.sayHello(name));
+
+    verifyNoInteractions(logger);
+
+    assertThat(exception.getMessage(), startsWith("Name is"));
+  }
+
+}
diff --git a/tinylog-provider/src/it/settings.xml b/tinylog-provider/src/it/settings.xml
new file mode 100644
index 0000000..12780df
--- /dev/null
+++ b/tinylog-provider/src/it/settings.xml
@@ -0,0 +1,35 @@
+
+
+  
+    
+      
+        true
+      
+      it-repo
+      
+        
+          local.central
+          
+            true
+          
+          
+            true
+          
+          @localRepositoryUrl@
+        
+      
+      
+        
+          local.central
+          
+            true
+          
+          
+            true
+          
+          @localRepositoryUrl@
+        
+      
+    
+  
+
diff --git a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerException.java b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerException.java
index 815f61d..4e98690 100644
--- a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerException.java
+++ b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerException.java
@@ -19,6 +19,12 @@
  */
 package io.github.vitalijr2.logging.mock.tinylog;
 
+import org.tinylog.provider.LoggingProvider;
+
+/**
+ * This exception is thrown then {@link MockTinylogProviderExtension} cannot inject a mock {@link LoggingProvider}
+ * instance.
+ */
 public class MockLoggerException extends RuntimeException {
 
   public MockLoggerException(String message, Throwable cause) {
diff --git a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProvider.java b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProvider.java
index a3e9815..4fcd682 100644
--- a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProvider.java
+++ b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProvider.java
@@ -30,6 +30,13 @@
 import org.tinylog.provider.ContextProvider;
 import org.tinylog.provider.LoggingProvider;
 
+/**
+ * Wraps a mock logger provider.
+ * 

+ * Use {@link MockTinylogProvider} to get access to a mock {@link LoggingProvider} instance. + * + * @since 1.1.0 + */ public class MockLoggerProvider implements LoggingProvider, MockLoggerCleaner { static final LoggingProvider MOCK_INSTANCE; diff --git a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProvider.java b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProvider.java index 56908b4..9795735 100644 --- a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProvider.java +++ b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProvider.java @@ -24,7 +24,28 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.api.extension.ExtendWith; +import org.tinylog.provider.LoggingProvider; +/** + * An annotation for injecting an instance of a mock {@link LoggingProvider} instance. + *

+ * A field of type {@link LoggingProvider} marked with the {@link MockTinylogProvider} annotation will be assigned a + * mock instance. This mock can then be used to test logging behavior. + *

+ * Example: + *


+ *   {@literal @}Test
+ *   void helloWorld() {
+ *     when(logger.getMinimumLevel(isNull())).thenReturn(Level.INFO);
+ *
+ *     assertDoesNotThrow(helloService::sayHelloWorld);
+ *
+ *     verify(logger).log(eq(Level.INFO.ordinal()), isNull(), eq(Level.INFO), isNull(), isNull(), anyString(), isNull());
+ *   }
+ * 
+ * + * @since 1.1.0 + */ @ExtendWith(MockTinylogProviderExtension.class) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) diff --git a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtension.java b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtension.java index bdd960b..8fe5946 100644 --- a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtension.java +++ b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtension.java @@ -28,6 +28,15 @@ import org.junit.jupiter.api.extension.TestInstancePostProcessor; import org.tinylog.provider.LoggingProvider; +/** + * A JUnit extension for injecting an instance of a mock {@link LoggingProvider} instance. + *

+ * This extension is used alongside an annotation. A field of type {@link LoggingProvider} marked with the + * {@link MockTinylogProvider} annotation will be assigned a mock instance. This mock can then be used to test logging + * behavior. + * + * @since 1.1.0 + */ public class MockTinylogProviderExtension implements TestInstancePostProcessor, ParameterResolver { @VisibleForTesting diff --git a/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/package-info.java b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/package-info.java new file mode 100644 index 0000000..5b77af0 --- /dev/null +++ b/tinylog-provider/src/main/java/io/github/vitalijr2/logging/mock/tinylog/package-info.java @@ -0,0 +1,7 @@ +/** + * Mock loggers for tinylog backed by Mockito. + * + * @since 1.1.0 + */ +package io.github.vitalijr2.logging.mock.tinylog; \ No newline at end of file diff --git a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProviderSlowTest.java b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProviderSlowTest.java index 0fd81ba..ea7b5eb 100644 --- a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProviderSlowTest.java +++ b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockLoggerProviderSlowTest.java @@ -36,9 +36,12 @@ void tearDown() { @DisplayName("Clear and reset the mock instance") @Test - void cleanAndReset() throws InterruptedException { + void cleanAndReset() { + // given + when(MockLoggerProvider.MOCK_INSTANCE.getMinimumLevel(isNull())).thenReturn(Level.INFO); + // when - provider.shutdown(); + Logger.info("test message"); provider.cleanAndReset(); // then diff --git a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionFastTest.java b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionFastTest.java index b128444..41f546a 100644 --- a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionFastTest.java +++ b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionFastTest.java @@ -86,6 +86,7 @@ void throwExceptionOnInjection() { static class JustTest { + @SuppressWarnings("unused") @MockTinylogProvider private LoggingProvider provider; diff --git a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionSlowTest.java b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionSlowTest.java index be19829..823e3cf 100644 --- a/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionSlowTest.java +++ b/tinylog-provider/src/test/java/io/github/vitalijr2/logging/mock/tinylog/MockTinylogProviderExtensionSlowTest.java @@ -69,6 +69,7 @@ void wrongType() { static class HappyTest { + @SuppressWarnings("unused") @MockTinylogProvider private LoggingProvider loggingProvider; @@ -76,12 +77,14 @@ static class HappyTest { static class UnannotatedFieldTest { + @SuppressWarnings("unused") private LoggingProvider loggingProvider; } static class WrongTypeTest { + @SuppressWarnings("unused") @MockTinylogProvider private String loggingProvider;