Skip to content

Logs truncated when using SystemErrGuard  #20

@chiaradiamarcelo

Description

@chiaradiamarcelo

Description

In test classes annotated with @ExtendWith(SystemErrGuard.class) and with multiple test cases that sniff the System.Err, the logs are truncated after the execution of the first test case.

An instance of java.util.logging.Logger uses by default ConsoleHandler that is bounded to a reference of the System.Err.
This binding happens upon creation of the Consolehandler, which is lazily instantiated, for example when logging a message with the logger for the first time (ie, LOGGER.info("message")).

If the System.Err is changed (ie, System.setErr(newSystemStream)), all the already existent instances of ConsoleHandler are not updated, so they don't log to the new System.Err.

Steps to Reproduce

  1. Implement the following classes
import java.util.logging.Logger;
public final class TesteableClass {
    public static final Logger LOGGER = Logger.getLogger(TesteableClass.class.getName());

    public static String testeableMethod() {
            LOGGER.info("TESTEABLE LOG MESSAGE");
    }
}
@ExtendWith(SystemErrGuard.class)
class TestClass {
    @Test
    void firstTestCase(final Capturable stream) {
          stream.capture();
          TesteableClass.testeableMethod();
          assertThat(stream.getCapturedData(), containsString("TESTEABLE LOG MESSAGE"));
    }
    @Test
    void secondTestCase(final Capturable stream) {
          stream.capture();
          TesteableClass.testeableMethod();
          assertThat(stream.getCapturedData(), containsString("TESTEABLE LOG MESSAGE"));
    }
}
  1. Execute the tests.
  2. Verify the console does not show all the logs (you can see in the console only one "TESTEABLE LOG MESSAGE" message instead of two)
  3. As a work around, you can reset the ConsoleHandler before executing each tests and disabling the use of the parent ConsoleHandler (cause if not it would log twice, once for each handler, during the execution of the first test), for example:
    @BeforeEach
    void beforeEach() {
        TesteableClass.LOGGER.setUseParentHandlers(false);
        final Handler[] handlers = TesteableClass.LOGGER.getHandlers();
        for (final Handler handler : handlers) {
            TesteableClass.LOGGER.removeHandler(handler);
        }
        TesteableClass.LOGGER.addHandler(new ConsoleHandler());
    }

Expected behavior

Tests should pass and "TESTEABLE LOG MESSAGE" should be visible twice in the console.

Environment

  • JUnit5 System Extensions: 1.1.0
  • OS: Ubuntu 20.04.1
  • Java Version: 11
  • Maven Version (in case of build problems only): 3.6.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions