Xwiki日志规则不捕获日志语句



我正在尝试使用XWiki LogRule来捕获日志记录器输出。没有捕获输出。不清楚我做错了什么。我已经阅读了相关的代码和文档,并且觉得我已经做了彻底的搜索-所有这些都无济于事。我选择了这个解决方案,因为它似乎是当前问题的最优雅的解决方案。

我正试图确定问题的范围以及从Mockito 1.8.5迁移到1.9.5所产生的问题的可能解决方案。我们过去可以在final字段中插入,但现在不能使用@ injectmock了,我明白为什么。

一个解决方案是删除final修饰符。另一种方法是创建重载构造函数并手动注入。第一个是令人不快的。第二个是丑陋的,因为它引入了仅用于测试的代码,并且在模拟日志记录器时,日志记录器是唯一的final字段。因此,在日志记录器是唯一问题的情况下,我认为使用XWiki -commons-test-simple-5.4.1.jar中提供的XWiki LogRule是有意义的。

下面是测试类中规则的实现:
@Rule
public LogRule logRule = new LogRule()
{
    {
        record(LogLevel.INFO);
        recordLoggingForType(EmployerNameCacheLoadServiceImpl.class);
    }
};

下面是测试中规则的执行:

@Test
public void testLoadCache_FormatAndLogData()
{
    String key = "key";
    String incorrectKey = key + " n random malicious text";
    String incorrectStorageId = STORAGE_ID + " n random malicious text";
    String incorrectUserGuid = USER_GUID + " n random malicious text";
    when(serviceUser.getOwningFirm()).thenReturn(incorrectStorageId);
    when(serviceUser.getUserGuid()).thenReturn(incorrectUserGuid);
    when(employerNameLoadSummaryCache.get(anyString())).thenReturn(null);
    when(searchableEmployerNameFactory.createSearchableEmployerNames(eq(serviceUser), anyString()))
        .thenReturn(new HashMap<String, SearchableEmployerName>());
    when(stringSecurityFormatter.formatString(incorrectKey)).thenReturn(key);
    when(stringSecurityFormatter.formatString(incorrectStorageId)).thenReturn(STORAGE_ID);
    when(stringSecurityFormatter.formatString(incorrectUserGuid)).thenReturn(USER_GUID);
    employerNameCacheLoadService.loadCache(serviceUser, incorrectKey);
    verify(stringSecurityFormatter).formatString(incorrectKey);
    verify(stringSecurityFormatter).formatString(incorrectStorageId);
    verify(stringSecurityFormatter).formatString(incorrectUserGuid);
    String expectedLogEntry =
        String.format("Cache load(%s) of firm (%s) for batch (%s) by user(%s). A total of %d entries.",
                      key,
                      STORAGE_ID,
                      anyString(),
                      USER_GUID,
                      0);

// 验证(logger) . info (expectedLogEntry);System.out.println("this.logRule.size() is " + this.logRule.size());System.out.println("this.logRule.toString() is " + this.logRule.toString());为了(this.logRule.size (), (1));为了(this.logRule.getMessage (0), containsString (expectedLogEntry));为了(this.logRule.toString (), containsString (expectedLogEntry));}

你可以看到,我已经尝试了一些变化。对logRule.size()的调用返回0,它应该总是记录一个INFO条目。

下面是目标类中记录器的定义:

private final Logger logger = Logger.getLogger(EmployerNameCacheLoadServiceImpl.class);

下面是要测试的方法:

@Override
public String loadCache(final serviceUser user, final String key)
{
    NamesLoadSummary namesLoadSummary = employerNameLoadSummaryCache.get(key);
    String batchId = null;
    Date now = new Date();
    if (namesLoadSummary == null || now.after(namesLoadSummary.getExpiresDateTime()))
    {
        batchId = UUID.randomUUID().toString().replace("-", "");
        final Map<String, SearchableEmployerName> mapOfSearchableNames =
            searchableEmployerNameFactory.createSearchableEmployerNames(user, batchId);
        employerNamesCache.putAll(mapOfSearchableNames);
        namesLoadSummary = new NamesLoadSummary();
        namesLoadSummary.setBatchId(batchId);
        namesLoadSummary.setStorageId(key);
        namesLoadSummary.setExpiresDateTime(employerNameCacheExpiryCalculator.calculateExpiryDate());
        employerNameLoadSummaryCache.put(key, namesLoadSummary);
        logger.info(String.format("Cache load(%s) of firm (%s) for batch (%s) by user(%s). A total of %d entries.",
                                  stringSecurityFormatter.formatString(key),
                                  stringSecurityFormatter.formatString(user.getOwningFirm()),
                                  batchId,
                                  stringSecurityFormatter.formatString(user.getUserGuid()),
                                  mapOfSearchableNames.size()));
    }
    else
    {
        batchId = namesLoadSummary.getBatchId();
    }
    return batchId;
}

下面是控制台输出:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/c164033/tools/jars/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/c164033/.ivy2/cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
14:41:00,556 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
14:41:00,557 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:/C:/Users/c164033/workspace/Contacts/bin/logback-test.xml]
14:41:00,558 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback-test.xml] occurs multiple times on the classpath.
14:41:00,558 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback-test.xml] occurs at [jar:file:/C:/Users/c164033/tools/jars/xwiki-commons-test-simple-5.4.1.jar!/logback-test.xml]
14:41:00,558 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback-test.xml] occurs at [file:/C:/Users/c164033/workspace/Contacts/bin/logback-test.xml]
14:41:00,621 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
14:41:00,669 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
14:41:00,681 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
14:41:00,707 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
14:41:00,783 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - com.xxx.yyy.zzz level set to INFO
14:41:00,783 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - org.hibernate level set to ERROR
14:41:00,783 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to WARN
14:41:00,783 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
14:41:00,783 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
14:41:00,784 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@1a7553 - Registering current configuration as safe fallback point
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
2014-03-21 14:41:01,037 INFO  [main] EmployerNameCacheLoadServiceImpl: Cache load(key) of firm (storageId) for batch (ded2a5d7c9124fa0b3269afe355001e0) by user(userGuid). A total of 0 entries.
this.logRule.size() is 0
this.logRule.toString() is com.xxx.yyy.zzz.contacts.employer.name.EmployerNameCacheLoadServiceImplTests$1@9fa7ba

如您所见,它实际上记录了日志。您还可以看到有一些slf4j绑定警告。似乎这些都不是问题,但一旦这篇文章发布,我们就会进一步研究这个角度。

我正在寻找是解决这个问题的建议,以便LogRule将捕获记录的输出。

我意识到-在我最初发布之后-我没有将logback-test.xml添加到我的项目中。这样做,测试仍然失败,但控制台是不同的。上面的控制台日志现在反映了这个更改。

这是我的log4j.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
    <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p [%t] %c{1}: %m%n"/>
        </layout>
    </appender>
    <logger name="com.xxx.yyy.zzz">
        <level value="INFO" />
    </logger>
    <logger name="org.hibernate">
        <level value="ERROR" />
    </logger>
    <root>
        <level value="WARN"/>
        <appender-ref ref="ConsoleAppender"/>
    </root>
</log4j:configuration>

下面是前面提到的logback-test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!--
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
<!-- Logback Test configuration that only logs at error level -->
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <!-- It's important that we log with the same default values as the ones used at runtime, so that tests see what
       is really printed at runtime. Thus tests should capture their output to not print anything in the console
       and assert what's printed using the LogRule class. -->
    <logger name="com.xxx.yyy.zzz">
        <level value="INFO" />
    </logger>
    <logger name="org.hibernate">
        <level value="ERROR" />
    </logger>
  <root level="warn">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Bill,我不知道是什么问题,但是我只是想让你知道XWiki项目在这里发布了一个新的日志记录规则。也许新规定对你更有效?

https://github.com/xwiki/xwiki-commons/blob/master/xwiki-commons-tools/xwiki-commons-tool-test/xwiki-commons-tool-test-simple/src/main/java/org/xwiki/test/AllLogRule.java

最新更新