xwiki logrule不捕获日志语句

时间:2014-03-21 19:15:20

标签: logging mockito xwiki junit-rule

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

我正在尝试确定问题的范围以及从Mockito 1.8.5迁移到1.9.5所产生的问题的可能解决方案。我们曾经能够插入到最终字段中,并且不再能够 - 我理解为什么 - 使用@InjectMocks。

一种解决方案是删除最终修饰符。另一种方法是创建重载的构造函数并手动注入。第一个是难吃的。第二个是丑陋的,因为它引入了仅用于测试的代码,并且在模拟记录器时,记录器是唯一的最终字段。因此,在记录器是唯一的问题的情况下,我认为使用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);

// verify(logger).info(expectedLogEntry);         System.out.println(“this.logRule.size()is”+ this.logRule.size());         System.out.println(“this.logRule.toString()is”+ this.logRule.toString());         assertThat(this.logRule.size(),是(1));         assertThat(this.logRule.getMessage(0),containsString(expectedLogEntry));         assertThat(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>

1 个答案:

答案 0 :(得分:0)

比尔,我不知道问题是什么,但我只是想让你知道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