我有一个将消息写入某些日志的类。该类是一个不做任何其他事情的实用程序,它在后台运行,检查一些事情并记录它们。我想知道我是否可以在单元测试中验证日志已被写入而不关心它实际写入的内容。这是我正在测试的课程:
//imports...
public class MyClass {
private static Log log = LogFactory.getLog(MyClass.class);
public MyClass() {
log.info("MyClass is being created.");
}
public void doThing() {
if( everything_is_fine ) {
log.info("This is a message to say everything is fine.");
} else {
log.error("Uh oh...");
}
}
}
还有我的测试员班:
// imports ...
@RunWith(PowerMockRunner.class)
@PrepareForTest({MyClass.class,LogFactory.class})
public class MyClassTest {
Log mockLog;
@Before
public void setup() {
PowerMockito.mockStatic(LogFactory.class);
mockLog = mock(Log.class);
PowerMockito.when(LogFactory.getLog(MyClass.class)).thenReturn(mockLog);
}
@Test
public void test_everything_is_ok() {
MyClass mything = new MyClass(); // should write to log.info
mything.doThing(); // should write to log.info
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, never()).error(anyString());
}
@Test
public void test_everything_is_not_ok() {
MyClass mything = new MyClass(); // should write to log.info
// do something which makes things not ok
mything.doThing(); // should write to log.error
verify(mockLog, atLeastOnce()).info(anyString());
verify(mockLog, atLeastOnce()).error(anyString());
}
}
当我运行测试时,我希望 log.info() 为两个测试调用,而 log.error() 只为第二个调用。但是,对于这两个测试,我都得到了 log.info 的“通缉但未调用”。第二个是 log.error。所以要么:
1)我的代码坏了,没有写入日志,或者
2)我的测试坏了。
我在想我在测试中搞砸了一些东西,可能是非常明显的东西,所以有没有人有过测试这样的东西的经验可以帮助我?任何和所有的帮助将不胜感激。
更新:
感谢提供帮助的人,我现在有了解决方案。
在玩了一会儿代码后,我发现日志的初始化似乎有问题。这样private static Log log = LogFactory.getLog(MyClass.class);
做似乎没有正确使用模拟,所以如果我将它移动到构造函数,它似乎被模拟了,我的测试都按预期工作:
public class MyClass {
private static Log log;
public MyClass() {
MyClass.log = LogFactory.getLog(MyClass.class);
log.info("MyClass is being created.");
}
// etc ...
}
我现在可以正常工作了,但是谁能解释为什么以第一种方式初始化日志不起作用?或者也许指向我解释它的地方?我不确定我对 Java 如何初始化对象的理解是否存在差距,或者它是否是模拟框架的限制。