- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个包含 2 个条件的方法。在每种情况下,都会调用 Logger.error 方法。验证该方法调用的第一个测试成功,但任何其他测试都失败并显示
Wanted but not invoked...Actually, there were zero interactions with this mock.
有谁知道为什么会这样?
下面,我提供了一个示例类和一个将产生问题的单元测试:
package packageName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class X {
private static final Logger LOGGER = LoggerFactory.getLogger(X.class);
public void execute(boolean handle1stCase) {
if (handle1stCase) {
LOGGER.error("rumpampam");
} else {
LOGGER.error("latida");
}
}
}
测试:
package packageName;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
@RunWith(PowerMockRunner.class)
@PrepareForTest({LoggerFactory.class})
public class XTest {
@Mock
private Logger loggerMock;
private X x;
@Before
public void construct() {
MockitoAnnotations.initMocks(this);
mockStatic(LoggerFactory.class);
when(LoggerFactory.getLogger(any(Class.class))).thenReturn(loggerMock);
x = new X();
}
@Test
public void whenFirstCaseErrorLogged() throws Exception {
x.execute(true);
verify(loggerMock, times(1)).error("rumpampam");
}
@Test
public void whenSecondCaseErrorLogged() throws Exception {
x.execute(false);
verify(loggerMock, times(1)).error("latida");
}
}
结果:
Wanted but not invoked: loggerMock.error("latida"); -> at packageName.XTest.whenSecondCaseErrorLogged(XTest.java:51)
Actually, there were zero interactions with this mock.
编辑:
我简短地回答了为什么除了第一个之外的每个测试都在 comment of this answer 中失败了。 .
我对问题的解决方案:
在测试中提供:
public static Logger loggerMockStatic;
比只为所有测试创建一个实例并将其提供在静态变量中,并从比起使用静态 loggerMockStatic。所以你会:
...
MockitoAnnotations.initMocks(this);
if (loggerMockStatic == null) {
loggerMockStatic = loggerMock;
}
mockStatic(LoggerFactory.class);
//when(LoggerFactory.getLogger(any(Class.class))).thenReturn(loggerMock);
when(LoggerFactory.getLogger(any(Class.class))).thenReturn(loggerMockStatic);
...
并在验证方法中使用 loggerMockStatic 而不是 loggerMock。
一些关于方法的想法:
对我来说这很好,因为
1. 它不会破坏设计(如果您认为所需的变量应该是一个常量,那么它将保持这种状态)。
2. 它在测试中仅添加了 4 行,可让您测试常量(在本例中为记录器)行为。没有太多污染,测试用例仍然清晰。
我在 this answer 中解释的“删除 final 并提供 setter”方法打开系统漏洞。不需要有人为类设置记录器,我总是希望系统按需要打开。只为测试需要提供 setter 是不希望的。测试应该为实现工作,而不是相反。
特别是关于测试日志记录,我不认为应该在一般(大多数)情况下测试日志记录。日志记录应该是应用程序的一个方面。当您有其他输出来测试特定路径时,应该测试这些输出。但是在这种情况下(可能还有其他情况)某个路径没有其他输出,比如在某个条件下记录和返回,需要测试日志(根据我的说法)。我想始终知道即使有人更改了条件,日志消息仍将被记录。如果没有日志,并且如果有人以错误的方式更改了条件,则将无法知道错误是否存在于这段代码中(调试除外)。
我和一些同事讨论过,有一个单独的类来进行日志记录就可以了。这样常量在另一个类中被隔离,您将能够仅使用 Mockito 检查行为。他们进一步表示,如果您想将日志发送到电子邮件,则更改起来会更容易。
首先,如果您不打算在不久的将来在日志记录方式之间切换,我认为这是一个过早的模块化。
其次,仅使用 Mockito + 具有另一个类和 + 3 行代码 VS 我的一行代码 (logger.error(...)) + 使用 PowerMockito,我将再次使用后者。在测试期间添加额外的依赖项不会使您的生产代码变慢和变大。也许在考虑继续集成并且测试与其他阶段一样重要时,您可能会说这会使测试过程变得更慢、更庞大,但我会牺牲这一点——这对我来说似乎没什么大不了的。
最佳答案
您的记录器是静态的,因此它是在您的类加载时加载的,而不是在对象初始化时加载的。您无法保证您的模拟会按时准备好,有时它可能会工作有时不会。
关于java - Mockito 无法验证来自 org.slf4j.Logger 的方法的多次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20196138/
作为一个新人中的菜鸡,最近在看一个项目的代码其中有这么一段看得我很是费解 public class AssembleMsgService { private static Logger logger
我已更改 Gradle 构建脚本以使用 Spring 2.0.1 而不是 1.5.9。当我运行 gradle build 时,出现错误:找不到符号 Logger logger = Logger.get
这是我的示例代码: public class Logs { private static Logs logHandler; public static Logs handler() {
我目前正在使用 Java 日志记录。我有一个记录器 cwh.A 和 cwh.B。是否可以通过 Java 从记录器 cwh 获取这些记录器,而不知道它们的名称? 最佳答案 可以通过日志管理器获取所有记录
在我的应用程序中,有一次我将 java.util.logging 的根 Logger 及其所有处理程序设置为 Level.FINEST,如下所示: Logger.getLogger("").setLe
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 7 年前。 Improv
我刚刚将 Java 插件升级到 1.7.0_25,这导致我几年前编写的一个小程序出现 fatal error (此后一直在维护)。 在小程序的 init() 方法的早期,我调用了 logger = L
logger.debug 和 logger.info 有什么区别? logger.debug什么时候打印? 最佳答案 我建议你看看这篇名为 "Short Introduction to log4j"
Fixed I tried reinstalling the plugin but that didn't work so i completely cleared my inteljii idea
我定义了一个记录器实例如下: private static final Logger LOGGER = Logger.getLogger(Main.class.getName()); 我有一个要记录的
我正在 Windows 下使用 Python 3.4.2。就我而言, import logging logger = logging.getLogger('logger') logger.setLev
我目前正在使用 C# 开发一个新的 Prism 项目,并想在我的 Bootstrapper 类中创建一个 NLog Logger。不幸的是,无论我做什么,它都拒绝构建,并告诉我... 'Logger.
我已经有几年没有使用 Log4J 了。我现在正在使用 org.jboss.logging 包在 JBoss 5 下开发一个应用程序。当我以前这样做时,将 logger.info() 消息包含在日志记录
ActiveRecord::Base.logger = Logger.new(STDOUT) 的 redis 等价物是什么?我想看看redis在做什么。 最佳答案 $redis.client.logg
我正在尝试使用 log4js 创建日志文件。完成所有配置后运行 Node app.js 时,我收到以下错误。 错误: TypeError: logger.setLevel is not a funct
我在一个拥有大约 50 多名开发人员的 IT 部门工作。它曾经有大约 100 多名开发人员,但由于经济衰退而被削减。 当我们的部门规模扩大时,我们雄心勃勃地努力建立一个特殊的架构小组。 这个小组决定做
我正在尝试找出跨多个模块使用 python 日志记录的最佳实践。我在这里看到:http://docs.python.org/2/howto/logging#logging-from-multiple-
我想将 Logger 注入(inject)到在 WildFly 10 上运行的 Maven 动态 Web 项目中的 bean 中。 我在 POM 中添加了依赖项。 WildFly 中提供了范围:
Java 9 引入了一个新的记录器,即 java.lang.System.Logger但我们总是有java.util.logging.Logger . 此记录器有什么新功能以及它有何改进? 最佳答案
我在 eclipse Mars 中配置了我的环境,但是 log4j 出现错误。我使用 spring 4 和 Maven 作为依赖管理器。部分代码: Eclipse 在这一行显示了一个错误,等于后的第二
我是一名优秀的程序员,十分优秀!