Comments (7)
Sorry for the late answer, i was quite busy - but just wanted to return the thank you for the follow up :)
from log-captor.
Hi @Emprah
Thank for reporting this issue and sharing the detailed code snippets! Could you retry with the latest version and tell me if the issue is still present? The latest version is 2.7.2
and is able to capturing logs within a multi thread setup.
from log-captor.
I tried again with 2.7.2, but no difference unfortunately...
from log-captor.
I have tried it locally and indeed I am getting the same behaviour which you mentioned. Reusing log captor works and I use it at some other places such as here: unit test example So I was amazed to see this issue.
I tried couple of different scenario's with the code snippet you have shared and I noticed that when I don't use SpringBootIntegrationTest annotation and try static field, with reusing logcaptor
it works. So my assumption is that the spring annotation is messing things up for this specific setup. I investigated it but could not found the issue, so I ended up creating a stackoverflow question here: https://stackoverflow.com/questions/70259059/logcaptor-fails-to-capture-when-using-springboottest-annotation
For now I don't have a fix as I am not able to understand why the spring boot annotation messes logcaptor while using it as a static field. So I would suggest to use the following snippet for now till I have more info regarding this issue.
private LogCaptor logcaptor;
@BeforeEach
void setupLogCaptor() {
logcaptor = LogCaptor.forClass(FooService.class);
}
@AfterEach
void closeLogCaptor() {
logcaptor.close();
}
You could also use the following setup for the time being:
@SpringBootIntegrationTest
class TestClass {
private LogCaptor logcaptor;
private Sut sut;
@Autowired
TestClass(Sut sut) {
this.sut = sut;
this.logcaptor = LogCaptor.forClass(Sut.class);
}
@BeforeEach
void beforeEach() {
logcaptor.clearLogs();
}
private static Stream<List<String>> provideParameters() {
return Stream.of(
null,
List.of()
);
}
@ParameterizedTest
@MethodSource("provideParameters")
void testMethod(List<String> parameters) {
CompletableFuture<void> future = sut.doStuff(parameters);
assertThrows(Exception.class, () -> future.get(10, TimeUnit.SECONDS));
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}
}
or the following snippet:
@SpringBootIntegrationTest
class TestClass {
private LogCaptor logcaptor;
@Autowired
private Sut sut;
@PostConstruct
void init() {
logcaptor = LogCaptor.forClass(Sut.class);
}
@BeforeEach
void beforeEach() {
logcaptor.clearLogs();
}
private static Stream<List<String>> provideParameters() {
return Stream.of(
null,
List.of()
);
}
@ParameterizedTest
@MethodSource("provideParameters")
void testMethod(List<String> parameters) {
CompletableFuture<void> future = sut.doStuff(parameters);
assertThrows(Exception.class, () -> future.get(10, TimeUnit.SECONDS));
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}
}
from log-captor.
I got a reply on this issue from someone on stackoverflow and he mentioned the following:
The problem in the failing test is that the class variable logcaptor is created before the test application context is created. During the bootstrapping of the test application context, Spring Boot will completely configure logback from scratch. This causes the appender that was added in LogCaptor::forClass to get lost.
In the successful @SpringBootTest tests, the appender is added in a much later stage of the context lifecycle.
You can get the test to pass when you take any of the two passing @SpringBootTest tests and execute them together as long as the failing test is not executed first. That's because the Spring test framework will not bootstrap a new context but re-use the context of the first test that was run. You can get the test back to failing if you annotate its class with @DirtiesContext(classMode = ClassMode.BEFORE_CLASS) because then again a new context will be created after the class variable logcaptor is assigned.
I'm afraid that there is little one can do about this. This comment on github by the Spring Boot team is about a similar problem: spring-projects/spring-boot#19323 (comment)
source: https://stackoverflow.com/a/70310499/6777695
This issue is exactly the same as this one: spring-projects/spring-boot#19323 (comment) So I am not able to fix this on my side as it is a spring-boot related issue. So my advice would be to initialise LogCaptor after spring-boot has initialised the application context. This can be done by adding LogCaptor either in the BeforeAll
, BeforeEach
, Constructor
, PostConstruct
or in the test method.
So I am closing this issue as it is spring-boot related. Thank you for sharing this issue as it gave me more insight of how spring-boot is working and how LogCaptor is behaving in different kind of setups. I appreciate your investigation for the different scenario's 😊
from log-captor.
@Hakky54 maybe you could introduce something like resetCaptor
(that reassigns internally) so we can just do
@BeforeEach
void setupLogCaptor() {
logCaptor.resetCaptor();
}
for such cases?
from log-captor.
Hi @hoangbnc
Thank you for the suggestion, however this won't solve the root issue which is causing this different behavior. Adding a reset function and calling that in the before each is not different than just initializing it at that level. I think the ideal solution for this kind of use case or rather generic use case when using spring with junit 4 or 5 would be creating a junit-extension for logcaptor which would take away all of the verbosity for creating, resetting and disposal of logcaptor in the different test phases such as before all, before each, after each and after all.
from log-captor.
Related Issues (20)
- ConcurrentModificationException in getLogs() 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
- consoleCaptor.getStandardOutput() doesn't work HOT 6
- 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
- Documentation Request for Use in Quarkus; Problem with SLF4J HOT 4
- ava.lang.NoClassDefFoundError: org/slf4j/spi/LoggingEventAware HOT 13
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.