Comments (6)
It seems like the main issue is because of the @QuarkusTest
annotation. I discovered that QuarkusTest
is using a ConsoleHandler from the Jboss Logger library. The ConsoleHandler uses the System.out to log everything to the console. ConsoleCapture should manipulate the System.out, but fails to because the ConsoleHandler is initialized before ConsoleCaptor because of the QuarkusTest annotation. The good news is that I found a solution, however it will take some time to finilize it. I think by one week it should be ready, maybe earlier. So my advice is to drop LogCaptor as it is having issues because of multiple classloaders caused by Quarkus, which is unfortunally not fixable. And just wait for the new release of ConsoleCaptor.
from log-captor.
Hi Eric,
I would advice not using ConsoleCaptor alongside with LogCaptor as it can conflict each other. I am not sure if that is the cause of the issue. But can you try to remove LogCaptor from your project and also from your pom?
from log-captor.
Hi Eric,
I would advice not using ConsoleCaptor alongside with LogCaptor as it can conflict each other. I am not sure if that is the cause of the issue. But can you try to remove LogCaptor from your project and also from your pom?
I just removed it and still the same issue exist. This is basically a copy paste of the example and the only difference is that my logger is JBoss, could that be the cause?
But I also changed the logger to SLF4J and still the issue exist.
from log-captor.
Hi again Eric,
It seems I have made a mistake during the testing late in the night. The @QuarkusTest
annotation was disabled. Although I had a fix ready it still didn't work because of the different classloader issue caused by @QuarkusTest
annotation.
With ConsoleCaptor you can capture the logs while removing the @QuarkusTest
annotation, but then you need to add ConsoleCaptor as a javaagent which is complex to set it up. I would rather provide you an easy solution.
I have now a working solution with LogCaptor. I used the following code snippets:
In my pom I needed to exclude the slf4j implementation provided by Jboss. In that way LogCaptor can use his own slf4j implementation
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${version.maven-surefire-plugin}</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.jboss.slf4j:slf4j-jboss-logmanager</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
Example greetings resource with JBossLog annotation from LomBok
import lombok.extern.jbosslog.JBossLog;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@JBossLog
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
log.info("Saying hello from the logger!");
return "Hello from RESTEasy Reactive";
}
}
And the test class:
import nl.altindag.log.LogCaptor;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class GreetingsResourceWithoutQuarkusTestShould {
@Test
void sayHello() {
LogCaptor logCaptor = LogCaptor.forClass(GreetingResource.class);
new GreetingResource().hello();
Assertions.assertThat(logCaptor.getLogs()).contains("Saying hello from the logger!");
}
}
The above example works. If you need any help with it I can also create an example project so you can try it out yourself.
I also tried with the Quarkus test annotation, but than I am having a run time exception, see below:
import io.quarkus.test.junit.QuarkusTest;
import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hamcrest.Matchers.is;
@QuarkusTest
public class GreetingsResourceWithQuarkusTestShould {
@Test
void sayHello() {
assertThatThrownBy(LogCaptor::forRoot)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Multiple classloaders are being used. " +
"The Logging API is created by the following classloader: [jdk.internal.loader.ClassLoaders$AppClassLoader], " +
"while it should have been created by the following classloader: [io.quarkus.bootstrap.classloading.QuarkusClassLoader].");
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Hello from RESTEasy Reactive"));
}
}
So the downside is you can not use Quarkus test and RestAssured if you want to test your business logic and also want to test your logs together in the same test file. I would advice to keep them separate and use the first working example for just asserting the logs. Hope this will help you. Please let me know if this will work for you
from log-captor.
Hi @Jerilok
I gave a last attempt and I manage to get it working. It was troublesome, but it works for LogCaptor and ConsoleCaptor! I would still advice to go with ConsoleCaptor as it also works with the @QuarkusTest
annotation. So forget all of my previous replies 😄
See here for a working demo:
- Unit testing logs with ConsoleCaptor while using Quarkus with Jboss logging and Lombok
- Unit testing logs with LogCaptor while using Quarkus with Jboss logging and Lombok
The steps below is for setting up console captor!
So what you need to do is:
- Add logback-classic as test dependency
- Add logback-test.xml as test resource
- Configure surefire plugin to exclude their slf4j logging implementation
So your pom.xml should be something like this:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${version.lombok}</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${version.jboss-logging}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${version.logback-classic}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>consolecaptor</artifactId>
<version>${version.consolecaptor}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${version.assertj-core}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${version.maven-surefire-plugin}</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>org.jboss.slf4j:slf4j-jboss-logmanager</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Your logback-test.xml file should have the following content:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="TRACE">
<appender-ref ref="STDOUT" />
</root>
</configuration>
This is an example greeting resource:
import lombok.extern.jbosslog.JBossLog;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@JBossLog
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
log.info("Saying hello from the logger!");
return "Hello from RESTEasy Reactive";
}
}
And the working test class:
import io.quarkus.test.junit.QuarkusTest;
import nl.altindag.console.ConsoleCaptor;
import org.junit.jupiter.api.Test;
import java.util.List;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertTrue;
@QuarkusTest
public class GreetingsResourceShould {
@Test
void successfullyCapturesLogs() {
try(ConsoleCaptor consoleCaptor = new ConsoleCaptor()) {
new GreetingResource().hello();
List<String> standardOutput = consoleCaptor.getStandardOutput();
assertThat(standardOutput).isNotEmpty();
assertTrue(standardOutput.stream().anyMatch(message -> message.contains("Saying hello from the logger!")));
}
}
@Test
void successfullyCapturesLogsAlternativeWhileUsingRestAssured() {
try(ConsoleCaptor consoleCaptor = new ConsoleCaptor()) {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Hello from RESTEasy Reactive"));
List<String> standardOutput = consoleCaptor.getStandardOutput();
assertThat(standardOutput).isNotEmpty();
assertTrue(standardOutput.stream().anyMatch(message -> message.contains("Saying hello from the logger!")));
}
}
}
Can you give it a try and share your results here?
from log-captor.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
from log-captor.
Related Issues (20)
- Expose MDC logback property map in LogEvent HOT 4
- Add existing contributors HOT 11
- ConcurrentModificationException in getLogs() HOT 7
- Logcaptor error logs do not contain expected content when reusing instance HOT 7
- log4j HOT 1
- Running the unit test directly from IDEA gives error HOT 7
- Not working with org.jacoco:jacoco-maven-plugin HOT 6
- There appears to be a classloading problem when using LogCaptor with `@QuarkusTest` test classes HOT 2
- LogEvent should implement toString() HOT 4
- Not compatible with log4j2 2.17.2 HOT 5
- Allow to retrieve logs for custom log levels HOT 2
- Does this project target Log4J API 1.7? HOT 9
- spring-boot-starter + log-captor: log4j-slf4j-impl cannot be present with log4j-to-slf4j HOT 5
- Upgrade to 2.8.0 HOT 18
- Suppressing Console Output HOT 3
- Are we supposed to close LogCaptor at the end of a test? HOT 3
- Issue with custom levels HOT 3
- Seeing DEBUG level logs after adding logcaptor dependency HOT 2
- disableConsoleOutput() is throwing NPE HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from log-captor.