### Question:
LoggingUtil { public static void log(Logger logger, LogLevel level, String message, Object... args) { level.log(logger, message, args); }  static void log(Logger logger, LogLevel level, String message, Object... args); static void log(Logger logger, LogLevel level, Class<E> tokensType, String message, Function<E, Object> tokenValueFunct); static void log(Logger logger, LogLevel level, Class<E> tokensType, String message, Throwable th, Function<E, Object> tokenValueFunct); static Object[] extractArguments(Class<E> tokensType, String message, Function<E, Object> tokenValueFunct); static Object[] extractArguments(Class<E> tokensType, String message, Throwable th, Function<E, Object> tokenValueFunct); static Object[] deriveArguments(List<E> tokens, Function<E, Object> tokenValueFunct); static Object[] deriveArguments(List<E> tokens, Throwable th, Function<E, Object> tokenValueFunct); static List<E> extractTokens(Class<E> tokensType, String message); static String toLogMessage(String message);  }### Answer:
@Test public void testTrace() { LoggingUtil.log(this.logger, LogLevel.TRACE, "log message", ARGS); Mockito.verify(this.logger).trace("log message", ARGS); }
@Test public void testWarnString() { LoggingUtil.log(this.logger, LogLevel.level("warn"), "log message", ARGS); Mockito.verify(this.logger).warn("log message", ARGS); }
@Test public void testDynamicSubstitution() { LoggingUtil.log(logger, LogLevel.ERROR, TestFields.class, "log message {AAA} {BBB} {CCC}", VALUES_FUNC); Mockito.verify(this.logger).error("log message {} {} {}", ARGS); }
@Test public void testDynamicWithException() { Exception ex = new IllegalArgumentException(); LoggingUtil.log(logger, LogLevel.DEBUG, TestFields.class, "log message {AAA} {BBB} {CCC}", ex, VALUES_FUNC); Object[] expectedArgs = Stream.concat(Arrays.stream(ARGS), Stream.of(ex)).toArray(Object[]::new); Mockito.verify(this.logger).debug("log message {} {} {}", expectedArgs); }