stefanbirkner / system-rules

A collection of JUnit rules for testing code which uses java.lang.System.
http://stefanbirkner.github.io/system-rules
Other
546 stars 71 forks source link

SystemErrRule fails to detect logged lines if it is being used in more than one junit test #51

Open imochurad opened 7 years ago

imochurad commented 7 years ago

I have a simple test, where I define a SystemErrRule as following:

    @Rule
    public final SystemErrRule systemErrRule = new SystemErrRule().enableLog();

Then I have 2 unit tests, where in each of them I test if there were lines dumped into system err. Only first JUnit test succeeds, the second one fails with:

Caused by: java.lang.AssertionError: 
Expecting:
 <"message=Unable to locate template, collection identifier (platform) is not supported, identifier=unknown">
to appear only once in:
 <"">
but it did not appear 

I'm using sl4j-simple as a dependency: testCompile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.16'

How do I fix it?

stefanbirkner commented 7 years ago

Your description does not contain enough information for providing you help. Can you show me the code that writes to System.err.

imochurad commented 7 years ago

Output to System.err is being made by Logback logger. LOGGER.error("blah")

stefanbirkner commented 7 years ago

I think that Logback gets a reference to the original System.err in the beginning and therefore still writes to the original System.err and not the one that is monitored by System Rules. If you want to test logging I recommend to check the logger instead of System.err. Here is how to do it: https://github.com/markkolich/logback-capturing-appender

imochurad commented 7 years ago

The approach you are suggesting is not robust. I have investigated GitHub repo of logback capturing appender, that appender, in order, to capture logging statements, have to have access to the actual Logger object, which is not accessible because it is private member of a class.

hoijui commented 5 years ago

I have this same problem, and it indeed happens because the logger has the original System.err as reference. When I manually re-instantiate the logger before logging, it works fine. Strangely though, even without this trick, it works fine for all test cases in all test classes, except in a single test-case, always the same one.

I have come along the suggestion to check the logger instead, but I consider that only as a dirty workaround, because I need to test my codes output to the OS, not what reaches the logger. The logger implementation can change, it might reach the logger but not get output, it might get formatted wrong by the logger, might be printed to the wrong stream, ... So I will stick with the dirty hack of re-initializing the logger for now, because this way I can at least test the right thing.

.. PS: thanks for the awesome library.. helps a lot! :-)