The following unit test will pass repeatedly in both your IDE (ex: run until failure) or in stressNewTest:
public class SystemOutRuleTest { @Rule public SystemOutRule systemOutRule = new SystemOutRule().enableLog(); @Test public void passesRepeatedly() { System.out.println("hello"); assertThat(systemOutRule.getLog()).contains("hello"); } } But the following test will fail after the first time the test is executed (ex: run until failure in IntelliJ) : public class SystemOutRuleTest { @Rule public SystemOutRule systemOutRule = new SystemOutRule().enableLog(); @Test public void passesFirstTime() { LogManager.getLogger().info("hello"); assertThat(systemOutRule.getLog()).contains("hello"); } } If you need to verify that a class is logging a specific message in some circumstances then you can extract that test from the Unit Test and move it to an Integration Test. You do *not* have to annotate SystemOutRule with @ClassRule but I recommend doing that especially if you're using other Rules doing some complicated setUp involving Geode classes: public class CacheLoggingIntegrationTest { private InternalCache cache; @Rule public SystemOutRule systemOutRule = new SystemOutRule().enableLog(); @Before public void setUp() { cache = (InternalCache) new CacheFactory().set(LOCATORS, "").create(); } @After public void tearDown() { cache.close(); } @Test public void passesFirstTime() { cache.getLogger().info("hello"); assertThat(systemOutRule.getLog()).contains("hello"); } } If you change the SystemOutRule in CacheLoggingIntegrationTest to a static @ClassRule: @ClassRule public static SystemOutRule systemOutRule = new SystemOutRule().enableLog(); ...then it will repeatedly pass if you run-until-failure in IntelliJ but only because IJ ends up running it as one test class. It will still fail when run repeatedly by stressNewTest or if a previous test class caused Log4J2 to startup within the same JVM. On Mon, Nov 26, 2018 at 1:46 PM Kirk Lund <kl...@apache.org> wrote: > Log4J and Logback both capture a reference to System.out and/or System.err > and then use that reference thereafter. This means that any manipulation of > System.out or System.err -- using System.setOut(PrintStream) or > System.setErr(PrintStream) -- probably isn't going to play nicely with > logging in general. > > Here's what that means for Geode tests... > > If you're writing a Unit Test, then that test will be executed in a > long-lived JVM in which other Unit Tests are also going to be executed. The > SystemOutRule from system-rules will work with code that uses System.out > directly but will not work repeatedly with loggers. > > If you're writing an Integration Test or Distributed Test, then that test > will be executed in a fresh JVM (fork every one is the config), so as long > as you can get the SystemOutRule before to invoke before logging, the test > will behave. In general that means you'll want to annotate it > with @BeforeClass. > > Here are a couple examples in which log4j2 captures System.out to > illustrate why SystemOutRule can't intercept the output after invoking > System.setOut(PrintStream): > > log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java:43: > private static final PrintStream DEFAULT_STREAM = System.out; > > log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLoggerContext.java:87: > ps = System.out; > > If SystemOutRule executes its before -- System.setOut(PrintStream) -- > after the above code, logging will be printing to a different PrintStream > than the PrintStream that SystemOutRule inserted into System. >