jcoglan opened a new pull request, #3256:
URL: https://github.com/apache/logging-log4j2/pull/3256

   Hi :wave: this is James from Neighbourhoodie, working on the STF agreed 
milestone to migrate the test suite to JUnit 5.
   
   This PR demonstrates an attempt to get a set of tests that use 
`@Parameterized` from JUnit 4 and try to get them running on JUnit 5. We have 
run into an odd problem where logger config files seem to be ignored and we're 
not sure how to resolve it.
   
   The class `DefaultRouteScriptAppenderTest` is parameterised like so:
   
   ```java
   @RunWith(Parameterized.class)
   public class DefaultRouteScriptAppenderTest {
   
       @Parameterized.Parameters(name = "{0} {1}")
       public static Object[][] getParameters() {
           return new Object[][] {
               {"log4j-routing-default-route-script-groovy.xml", false},
               {"log4j-routing-default-route-script-javascript.xml", false},
               {"log4j-routing-script-staticvars-javascript.xml", true},
               {"log4j-routing-script-staticvars-groovy.xml", true},
           };    
       }
   
       // ...
   }
   ```
   
   We need to replicate the effect of this parameterisation under JUnit 5. Our 
understanding is that, whereas in JUnit 4 it is the _constructor_ that is 
parameterised, in JUnit 5 the `@ParameterizedTest` annotation applies to 
individual test methods.
   
   The class also uses `LoggerContextRule`, and makes use of the API of that 
class to inspect the loggers/appenders that are configured. Our understanding 
is that this has been replaced with the class-level `@LoggerContextSource` 
annotation, which causes a `LoggerContext` to be passed into the constructor.
   
   This PR shows an idea we had for refactoring this test class to JUnit 5. 
Rather than label each of its individual tests as parameterised, and then have 
to invoke code to set up a `LoggerContext` and the necessary before/after hooks 
in each one, we observe that parameterisation can be achieved by subclassing. 
If the `DefaultRouteScriptAppenderTest` constructor accepts the parameters that 
define each "version" of the tests, then we can write subclasses of 
`DefaultRouteScriptAppenderTest` that each invoke their parent's constructor 
with different inputs.
   
   Since the parameterisation is expressed in the form of classes, we can then 
also use `@LoggerContextSource` on each of those classes to turn the config 
filename into a `LoggerContext` implicitly and not have to write/call any 
additional setup code ourselves.
   
   In the first commit we remove the `@Parameterized.Parameters` block and add 
several subclasses, each of which sets up the parent class with one of the 
parameter sets, e.g.
   
   ```java
   public class DefaultRouteScriptGroovyAppenderTest extends 
DefaultRouteScriptAppenderTest {
       public DefaultRouteScriptGroovyAppenderTest() {
           super("log4j-routing-default-route-script-groovy.xml", false);
       }
   }
   ```
   
   This works fine and the tests continue to pass.
   
   In the next commit, we attempt to migrate `DefaultRouteScriptAppenderTest` 
to JUnit 5, and as part of that we remove `LoggerContextRule` from that class 
and add `LoggerContextSource` to the subclasses:
   
   ```java
   @LoggerContextSource("log4j-routing-default-route-script-groovy.xml")
   public class DefaultRouteScriptGroovyAppenderTest extends 
DefaultRouteScriptAppenderTest {
       public DefaultRouteScriptGroovyAppenderTest(LoggerContext context) {
           super(context, false);
       }
   }
   ```
   
   We have tried to migrate the use of `LoggerContextRule` methods like 
`getListAppender()` to their equivalents on `LoggerContext`. However, these 
tests no longer pass; e.g. this is the result of running `mvn test 
-Dtest=ScriptStaticVarsJavaScriptAppenderTest`:
   
   ```
   
   ```
   [ERROR] Tests run: 8, Failures: 1, Errors: 6, Skipped: 0, Time elapsed: 
0.377 s <<< FAILURE! -- in 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest
                                                                                
        [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testListAppenderPresence
 -- Time elapsed: 0.012 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.getAppenders()" 
because the return value of 
"org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.getRoutingAppender()"
 is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testListAppenderPresence(DefaultRouteScriptAppenderTest.java:103)
                                                                                
                                              at 
java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)        
                                                                                
                                                                                
                                           at 
java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testNoPurgePolicy
 -- Time elapsed: 0.002 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.getPurgePolicy()"
 because the return value of 
"org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.getRoutingAppender()"
 is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testNoPurgePolicy(DefaultRouteScriptAppenderTest.java:109)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testRoutingPresence1
 -- Time elapsed: 0.007 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.isStarted()" 
because "routingAppender" is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.getListAppender(DefaultRouteScriptAppenderTest.java:69)
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.logAndCheck(DefaultRouteScriptAppenderTest.java:85)
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testRoutingPresence1(DefaultRouteScriptAppenderTest.java:133)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testRoutingPresence2
 -- Time elapsed: 0.001 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.isStarted()" 
because "routingAppender" is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.getListAppender(DefaultRouteScriptAppenderTest.java:69)
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.logAndCheck(DefaultRouteScriptAppenderTest.java:85)
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testRoutingPresence2(DefaultRouteScriptAppenderTest.java:139)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testNotListAppender
 -- Time elapsed: 0.001 s <<< FAILURE!
   org.opentest4j.AssertionFailedError: expected: not <null>
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testNotListAppender(DefaultRouteScriptAppenderTest.java:96)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testNoRewritePolicy
 -- Time elapsed: 0 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.getRewritePolicy()"
 because the return value of 
"org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.getRoutingAppender()"
 is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testNoRewritePolicy(DefaultRouteScriptAppenderTest.java:115)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   
   [ERROR] 
org.apache.logging.log4j.core.appender.routing.ScriptStaticVarsJavaScriptAppenderTest.testRoutingAppenderDefaultRouteKey
 -- Time elapsed: 0.001 s <<< ERROR!
   java.lang.NullPointerException: Cannot invoke 
"org.apache.logging.log4j.core.appender.routing.RoutingAppender.getDefaultRouteScript()"
 because "routingAppender" is null
           at 
org.apache.logging.log4j.core.appender.routing.DefaultRouteScriptAppenderTest.testRoutingAppenderDefaultRouteKey(DefaultRouteScriptAppenderTest.java:121)
           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
           at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
   ```
   
   It seems as though the config filename passed to `@LoggerContextSource` is 
being ignored -- changing the referenced files' content has no effect on the 
test outcome, and using a filename for a file that does not exist does not 
cause a different kind of failure. It just looks like the file is ignored 
entirely, and we're not sure why.
   
   Is there a quirk of `@LoggerContextSource` that means it doesn't work with 
subclassing, or something else we're not aware of? Should we be going about 
this in a different way, and if so how would you recommend turning a config 
filename into a working `LoggerContext`?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@logging.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to