问题描述
我正在为使用类似于以下记录器的遗留代码编写单元测试 :
public class MyLogger {
private static Logger logger;
public static void init() throws SomeException {
//initialize the logger field
}
public static Logger getLogger() {
return logger;
}
}
记录器需要初始化,否则返回null,并且由于使用记录器的被测代码产生NullPointerException
而导致测试失败 。
我的目标是测试遗留代码,而在测试时完全不依赖记录器(无论是否初始化)。
可能的解决方案:
-
在测试中添加对
MyLogger.init()
的调用-由于许多原因,这是不好的解决方案。 -
如果尚未初始化记录器,请在
getLogger
进行初始化-我不喜欢这种解决方案,因为这样getLogger
必须处理'SomeException'。 - 使用不执行任何操作的“ NullLogger”初始化记录器。
我选择了解决方案#3,但这需要我从Logger(具有大约60个函数)继承,并调用其构造函数,并仔细检查从我的代码中调用了logger的哪些方法,因此我可以选择适当的“空”实现。
我的问题有更好的解决方案吗?
1楼
使用NullLogger
框架创建NullLogger
。
您可以使用“ Mockito”或“ PowerMock”或“ EasyMock”或任何其他框架。
模拟对象是自动生成的子类,可以通过编程定义其行为。 默认情况下,模拟对象的功能将不执行任何操作并返回null(对于非void方法)。
您可能希望将记录器字段更改为打包隐私,以便能够在测试内部进行设置而不必使用反射。
使用Mockito 1.9.5的示例代码:
import java.util.logging.*;
import org.junit.Test;
import org.mockito.Mockito;
class SomeException extends Exception {
}
class MyLogger
{
static Logger logger; // changed to package privacy
public static void init() throws SomeException {
//initialize the logger field
}
public static Logger getLogger() {
return logger;
}
}
public class MyLoggerTest {
@Test
public void someTest() {
// set "NullLogger"
MyLogger.logger = Mockito.mock(Logger.class);
// access to logger won't fail anymore
MyLogger.getLogger().log(Level.SEVERE, "uninteresting stuff");
}
}