我试图测试一个静态方法,它捕获来自不同子调用或方法本身的异常,并只记录异常消息。根据要求,我无法更改方法实现。在这种情况下,监视子调用不是一个选项,因为我们希望在测试期间保持一致,并且由于一些执行会从方法体本身引发异常,所以我们最终选择检查。。。错误日志消息。
因此,我想模拟将从方法调用的记录器,当记录器调用错误(...)时,向日志记录调用添加一个答案,并与特定消息相匹配。到目前为止,我这边很好。我所做的一个例子如下:
Mockito.doAnswer(new Answer<Void>()
{
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String errorMessage = (String) args[0];
assertTrue(errorMessage.contains(SPECIFIC_MESSAGE));
return null;
}
}).when(logger).error(Matchers.startsWith(GENERIC_PREFIX));
我们决定使用PowerMockito来模拟静态调用,并从LoggerFactory.getLogger(...)
Logger logger = Mockito.mock(Logger.class);
PowerMockito.mockStatic(LoggerFactory.class);
Mockito.when(LoggerFactory.getLogger(any(Class.class))).thenReturn(logger);
现在我们的问题来了:
对于每个测试,要检查的特定消息的值都会发生变化。因此,我们为每个测试模拟一个记录器,模拟静态LoggerFactory调用以返回记录器,然后将我们的特定答案添加到记录器中。错误(…)打电话询问这个具体的例子。但是第一个答案被添加到记录器中。第一次测试中的错误调用似乎覆盖了所有其他答案。每次测试都会执行相同的操作。
我以为问题可能来自Mockito,它会返回一个单例模拟,但我测试了它,事实并非如此。然后我想我的问题可能来自我的争吵工厂。getLogger(…)调用,该调用将始终返回同一个记录器实例,但也不会返回该实例。下面是一个实现,它显示了我的代码与相关执行日志跟踪的相同问题。
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class App
{
public static Logger logger = LoggerFactory.getLogger(App.class);
public static void main(String[] args)
{
logger.error("Error = " + Arrays.toString(args));
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
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.Mockito.*;
import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({LoggerFactory.class})
public class AppTest
{
@Test
public void firstTest()
{
Logger logger = Mockito.mock(Logger.class);
PowerMockito.mockStatic(LoggerFactory.class);
Mockito.when(LoggerFactory.getLogger(any(Class.class))).thenReturn(logger);
Mockito.doAnswer(new Answer<Void>()
{
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String errorMessage = (String) args[0];
System.out.println("Calling from firstTest");
assertTrue(errorMessage.contains("a"));
return null;
}
}).when(logger).error(Matchers.startsWith("Error"));
App.main(new String[]{ "a" });
}
@Test
public void secondTest()
{
Logger logger = Mockito.mock(Logger.class);
PowerMockito.mockStatic(LoggerFactory.class);
Mockito.when(LoggerFactory.getLogger(any(Class.class))).thenReturn(logger);
Mockito.doAnswer(new Answer<Void>()
{
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String errorMessage = (String) args[0];
System.out.println("Calling from secondTest");
assertTrue(errorMessage.contains("b"));
return null;
}
}).when(logger).error(Matchers.startsWith("Error"));
App.main(new String[]{ "b" });
}
}
跟踪:
Calling from firstTest
Calling from firstTest
知道为什么第二个答案没有被处理吗?提前感谢。
编辑:
问题实际上来自静态方法mock。“然后我想我的问题可能来自我的LoggerFactory。getLogger(…)调用,该调用将始终返回同一个记录器实例,但也不会返回该实例。“实际上是错误的。在调用getLogger(…)的测试中,它是有效的。”返回在测试中模拟但实际调用应用程序时模拟的记录器。主要的(…)方法,模拟的getLogger(…)main(…)内部的方法调用始终返回相同的实例,并且在测试之间不会按预期重置。根据文档,Mockito应该在测试之间重置。mockito的缺陷还是局限?与Mockito和PowerMockito之间的交互有关的问题?
我找到了一个解决方案,就是为每个测试在方法级别为类准备静态模拟。在签名之前添加@PrepareForTest(LoggerFactory.class)
实际上解决了一个问题,即在测试和第一次调用Mockito之间没有重置记录器工厂模拟。when(LoggerFactory.getLogger(any(Class.Class)))。然后返回(记录器)
始终有效,并且始终返回相同的记录器。
是否有人使用RecyclerView找到了将onClickListener设置为RecyclerView中的项的方法? 请帮帮我...我是初学者:)
我知道匹配模式解析器,这是Spring批处理提供的。我需要关于如何构造批处理作业的帮助,以便它可以读取循环中的记录类型5和记录类型6。
我正在写基本的用户注册页面,我的注册页面包含:用户邮件,密码,计划类型。计划类型有三个计划。三种方案是:基本方案、银方案和金方案。 register_main.php是将用户信息存储在MySQL中。 我遇到的问题是,当我点击基本或银或黄金计划,页面将转到注册的主页。我只希望在他们单击“登录”时将用户信息发送到服务器。 有人能帮我解决这个问题吗? 超文本标记语言代码: register_main.p
我是Swift新手,这段代码给了我一个错误,尽管它没有文本,但它还是通过了“lastname!=nil”。 线程1:致命错误:在展开一个可选值时意外地找到nil 我很困惑,不知道为什么验证不起作用
河楼 我试图配置Hibernate本地开发与HSQL数据库,但我被困在Spring不处理事务。 配置数据源,会话工厂等... 本地环境具有hibernate配置的属性文件 引发异常的代码的调用点 调用人员Dao.saveOrUpdate()后打印的堆栈跟踪 我已经尝试过的 在HibernateTransactionManager/DatasourceTransactionManager之间切换 属