Java 在单元测试中是否有任何简单的 slf4j 使用模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3820290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:28:14  来源:igfitidea点击:

Is there any simple pattern of slf4j usage in unit tests?

javaslf4j

提问by yegor256

I'm using JUnit4 and Hibernate3 in my project. Hibernate depends on Slf4j and thus my project includes this library as well. Now I'd like to use Slf4j in unit tests in order to log supplementary testing information. Could you please provide a short example of how my unit test should look like in order to log just one line of text? Preferably without code duplicationin multiple tests.

我在我的项目中使用 JUnit4 和 Hibernate3。Hibernate 依赖于 Slf4j,因此我的项目也包括这个库。现在我想在单元测试中使用 Slf4j 来记录补充测试信息。你能否提供一个简短的例子来说明我的单元测试应该是什么样子,以便只记录一行文本?最好在多个测试中没有代码重复

采纳答案by Jim Tough

I also like to use slf4j in my JUnit tests for my DAO class. It does help when you are creating a new test or modifying an old one. I usually leave my old logging output at debug level, and make my new logging statements at info level while I'm still actively working on the code in that method. One of my JUnit classes would look something like this:

我还喜欢在 DAO 类的 JUnit 测试中使用 slf4j。当您创建新测试或修改旧测试时,它确实有帮助。我通常将旧的日志输出保留在调试级别,并在我仍在积极处理该方法中的代码时在信息级别创建新的日志语句。我的一个 JUnit 类看起来像这样:

package com.example.mydao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// other imports not shown...

public class TestMyDAO extends TestCase {

    private static final Logger logger = 
        LoggerFactory.getLogger(TestMyDAO.class);


    public void testA() {
        logger.debug("Logging from testA() method");
    }

    public void testB() {
        logger.debug("Logging from testB() method");
    }

    public void testThatIAmWorkingOn() {
        logger.info("Logging from my new test method at INFO level");
    }

}

I'm using log4j as the actual logging provider, so my log4j.xmlconfiguration file looks like this:

我使用 log4j 作为实际的日志记录提供程序,所以我的log4j.xml配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p  [%c{1}] %m %n" />
        </layout>
    </appender>

    <logger name="com.example.mydao" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.DriverManagerConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.C3P0ConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.resourcepool.BasicResourcePool" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.C3P0Registry" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <root>
        <priority value ="WARN" />
        <appender-ref ref="consoleAppender"/>
    </root>

</log4j:configuration>

This gives me the info-level output from my JUnit class, as well as some useful stuff from Hibernate runtime and other libraries used with Hibernate. Adjust to your own taste.

这为我提供了来自 JUnit 类的信息级输出,以及来自 Hibernate 运行时和其他与 Hibernate 一起使用的库的一些有用的东西。根据自己的口味调整。

Finally, I need to make sure that all of the following libraries are in my classpath when I execute the JUnit tests:

最后,当我执行 JUnit 测试时,我需要确保以下所有库都在我的类路径中:

  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml(my configuration file, shown above)
  • Some version of the JUnit runtime JAR
  • All the JARs normally present when running your application in production
  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml(我的配置文件,如上所示)
  • 某些版本的 JUnit 运行时 JAR
  • 在生产中运行应用程序时通常会出现所有 JAR

This is what I do when using log4j. If you use a different logging implementation, then adjust accordingly. It doesn't matter if you're using a different version of slf4j, as long as the "API" and implementation JARs are the same version (mine are both 1.6.0).

这就是我在使用 log4j 时所做的。如果您使用不同的日志记录实现,则相应地进行调整。如果您使用不同版本的 slf4j 并不重要,只要“API”和实现 JAR 是相同的版本(我的都是 1.6.0)。

回答by dty

Why do you want to log things in your unit test? Unit tests should be pass/fail and should use the testing framework to indicate that. You don't want to be reading through output to see if the test passed or failed. And if it's failing, running it in your IDE/debugger is the best way to fix it.

为什么要在单元测试中记录内容?单元测试应该是通过/失败,并且应该使用测试框架来表明这一点。您不想通读输出来查看测试是通过还是失败。如果它失败了,在您的 IDE/调试器中运行它是修复它的最佳方法。

回答by Adrian Shum

It seems to be a bad smell to me.

对我来说,这似乎是一种难闻的气味。

You should always avoid manual inspection or verification for unit test.

您应该始终避免对单元测试进行手动检查或验证。

Unit test should be automated, human intervention should only be needed if your build tools tell you that certain test failed, and the failure reason should be provided using all those verification methods (e.g. assertEquals)

单元测试应该是自动化的,只有当您的构建工具告诉您某些测试失败时才需要人工干预,并且应该使用所有这些验证方法(例如 assertEquals)提供失败原因

回答by BjornS

We use log4j as our output logger;

我们使用 log4j 作为我们的输出记录器;

private static Logger log = LoggerFactory.getLogger(MyClassHere.class);

slf4j should find and use log4j without issue if you configure it correctly. To make life easy, I would use this Eclipse pattern, since you will be writing this code a fair bit:

如果配置正确,slf4j 应该可以毫无问题地找到并使用 log4j。为了让生活更轻松,我将使用这个 Eclipse 模式,因为您将编写这段代码:

private static Logger log = LoggerFactory.getLogger(${enclosing_type}.class);
${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}

for tests I would recommend you don't rise above INFO level and keep most things to DEBUG. If you really want to trap lots of errors intelligently then I would recommend looking into PositronLogger which is a log file appender which will silently pick up on everything down to TRACE but only dump it to file if it captures ERROR; sort of like time travelling :)

对于测试,我建议您不要超过 INFO 级别并将大部分内容保留在 DEBUG 中。如果您真的想智能地捕获大量错误,那么我建议您查看 PositronLogger,它是一个日志文件附加程序,它会默默地获取所有到 TRACE 的所有内容,但只有在捕获到 ERROR 时才将其转储到文件中;有点像时间旅行:)

http://github.com/andreaja/PositronLogger

http://github.com/andreaja/PositronLogger

回答by Ed Griffin

If using log4j 1 as the underlying slf4j implementation

如果使用 log4j 1 作为底层 slf4j 实现

log4j doesn't log anything by default unless you,

log4j 默认不记录任何东西,除非你,

  • have a log4j.propertiesfile on the classpath
  • set -Dlog4j.configuration=file:///path/to/log4j.properties. If using maven this can be done in your maven-surefire-plugin configuration.
  • setup the log4j configuration programmatically, say in a @BeforeClass method

    @BeforeClass
    public static void beforeClass() {
        BasicConfigurator.resetConfiguration();
        BasicConfigurator.configure();
    }
    

    This just works, however it needs to be put on everyunit test which is a pain. So I don't recommend except if you temporarily need it to quickly get something to work.

  • log4j.properties在类路径上有一个文件
  • 设置-Dlog4j.configuration=file:///path/to/log4j.properties。如果使用 maven,这可以在您的 maven-surefire-plugin 配置中完成。
  • 以编程方式设置 log4j 配置,例如在 @BeforeClass 方法中

    @BeforeClass
    public static void beforeClass() {
        BasicConfigurator.resetConfiguration();
        BasicConfigurator.configure();
    }
    

    这只是有效,但是它需要放在每个单元测试中,这很痛苦。所以我不推荐除非你暂时需要它来快速获得一些工作。

回答by Ed Griffin

Another solution is to switch the logging implementation to a simple implementation just for tests.

另一种解决方案是将日志记录实现切换为仅用于测试的简单实现。

So in your pom.xml

所以在你的 pom.xml

    <!-- Depend on slf4j API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>

    <!-- Use SimpleLogger as the slf4j implementation in test -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.12</version>
        <scope>test</scope>
    </dependency>

    <!-- Use log4j as the slf4j implementation during runtime (not test) -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
        <scope>runtime</scope>
    </dependency>

The SimpleLogger just logs everything to stderr by default and doesn't require any configuration files

默认情况下,SimpleLogger 只是将所有内容记录到 stderr,不需要任何配置文件

回答by MrHari

Adding logging while writing new tests is useful. At the same time, when the tests are being run in a CI or CD pipeline, you want logging to be disabled (or at least less verbose). Sometimes the failures are transient especially in an end-to-end run, so having relevant output on the console log of CI jobs are helpful. This article describes it very well - https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

在编写新测试时添加日志很有用。同时,当测试在 CI 或 CD 管道中运行时,您希望禁用日志记录(或至少不那么冗长)。有时故障是暂时的,尤其是在端到端运行中,因此在 CI 作业的控制台日志上显示相关输出是有帮助的。这篇文章描述得很好 - https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

回答by user1917821

I didn't want to have to setup a xml file and I didn't want to use System.out.println. Mostly I needed this for unit tests.

我不想设置 xml 文件,也不想使用 System.out.println。大多数情况下,我需要这个进行单元测试。

You can set the test logger:

您可以设置测试记录器:

<!-- Use SimpleLogger as the slf4j implementation in test -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.7.12</version>
  <scope>test</scope>
</dependency>

Before you create your Logger set this property: (ref: http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.htmlother properties available other than TRACE)

在创建 Logger 之前设置此属性:(参考:http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html除 TRACE 之外的其他可用属性)

static {
    System.setProperty("org.slf4j.simpleLogger.defaultLogLevel","TRACE");
}

Create the logger:

创建记录器:

private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);


private void doSomeLogs(){
    LOGGER.trace("trace it"); 
}