### Question:
LoggingUtil { public static <E extends Enum<E>> Object[] extractArguments(Class<E> tokensType, String message, Function<E, Object> tokenValueFunct) { return extractTokens(tokensType, message).stream() .map(tokenValueFunct) .toArray(Object[]::new); }  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 testExtractArguments() { Object[] values = LoggingUtil.extractArguments(TestFields.class, "log message {AAA} {BBB} {CCC}", VALUES_FUNC); assertThat(values).containsExactly(ARGS); }
@Test public void testExtractArgumentsWithException() { Exception ex = new IllegalArgumentException(); Object[] values = LoggingUtil.extractArguments(TestFields.class, "log message {AAA} {BBB} {CCC}", ex, VALUES_FUNC); Object[] expectedArgs = Stream.concat(Arrays.stream(ARGS), Stream.of(ex)).toArray(Object[]::new); assertThat(values).containsExactly(expectedArgs); }