Asa*_*saf 47 java logging junit unit-testing log4j
我正在测试一个方法,当出现问题时记录警告并返回null.
就像是:
private static final Logger log = Logger.getLogger(Clazz.class.getName());
....
if (file == null || !file.exists()) {
// if File not found
log.warn("File not found: "+file.toString());
} else if (!file.canWrite()) {
// if file is read only
log.warn("File is read-only: "+file.toString());
} else {
// all checks passed, can return an working file.
return file;
}
return null;
Run Code Online (Sandbox Code Playgroud)
我想测试junit是否发出了警告,除了返回null之外,在所有情况下(例如找不到文件,文件是只读的).
有任何想法吗?
谢谢,asaf :-)
我对Aaron的回答的实现(加上彼得的评论):
public class UnitTest {
...
@BeforeClass
public static void setUpOnce() {
appenders = new Vector<Appender>(2);
// 1. just a printout appender:
appenders.add(new ConsoleAppender(new PatternLayout("%d [%t] %-5p %c - %m%n")));
// 2. the appender to test against:
writer = new StringWriter();
appenders.add(new WriterAppender(new PatternLayout("%p, %m%n"),writer));
}
@Before
public void setUp() {
// Unit Under Test:
unit = new TestUnit();
// setting test appenders:
for (Appender appender : appenders) {
TestUnit.log.addAppender(appender);
}
// saving additivity and turning it off:
additivity = TestUnit.log.getAdditivity();
TestUnit.log.setAdditivity(false);
}
@After
public void tearDown() {
unit = null;
for (Appender appender : appenders) {
TestUnit.log.removeAppender(appender);
}
TestUnit.log.setAdditivity(additivity);
}
@Test
public void testGetFile() {
// start fresh:
File file;
writer.getBuffer().setLength(0);
// 1. test null file:
System.out.println(" 1. test null file.");
file = unit.getFile(null);
assertNull(file);
assertTrue(writer.toString(), writer.toString().startsWith("WARN, File not found"));
writer.getBuffer().setLength(0);
// 2. test empty file:
System.out.println(" 2. test empty file.");
file = unit.getFile("");
assertNull(file);
assertTrue(writer.toString(), writer.toString().startsWith("WARN, File not found"));
writer.getBuffer().setLength(0);
}
Run Code Online (Sandbox Code Playgroud)
多谢你们,
Aar*_*lla 38
在单元测试的设置中:
添加一个记住列表中消息的appender:
public class TestAppender extends AppenderSkeleton {
public List<String> messages = new ArrayList<String>();
public void doAppend(LoggingEvent event) {
messages.add( event.getMessage().toString() );
}
}
Run Code Online (Sandbox Code Playgroud)将appender添加到记录器
现在你可以调用你的代码了.测试后,您将在列表中找到所有日志消息.如果需要(messages.add( event.getLevel() + " " + event.getMessage() );),请添加日志级别.
在tearDown(),再次删除appender并启用可加性.
jos*_*sle 16
使用Mockito,您可以使用最少的样板代码测试测试期间发生的日志记录,一个简单的示例是:
@RunWith(MockitoJUnitRunner.class)
public class TestLogging {
@Mock AppenderSkeleton appender;
@Captor ArgumentCaptor<LoggingEvent> logCaptor;
@Test
public void test() {
Logger.getRootLogger().addAppender(appender);
...<your test code here>...
verify(appender).doAppend(logCaptor.capture());
assertEquals("Warning message should have been logged", "Caution!", logCaptor.getValue().getRenderedMessage());
}
}
Run Code Online (Sandbox Code Playgroud)
这篇文章中的例子非常有用,但我发现它们有点令人困惑.
所以我为上面添加了一个简化版本,并进行了一些细微的修改.
这样,默认情况下,假设加法为真,我不需要担心由于记录器层次结构而导致丢失事件.确保这符合您的log4j.properties文件配置.
在AppenderSkeleton中附加处理级别过滤,所以我不想错过它.
如果级别正确,doAppend将调用append.
public class TestLogger {
@Test
public void test() {
TestAppender testAppender = new TestAppender();
Logger.getRootLogger().addAppender(testAppender);
ClassUnderTest.logMessage();
LoggingEvent loggingEvent = testAppender.events.get(0);
//asset equals 1 because log level is info, change it to debug and
//the test will fail
assertTrue("Unexpected empty log",testAppender.events.size()==1);
assertEquals("Unexpected log level",Level.INFO,loggingEvent.getLevel());
assertEquals("Unexpected log message"
,loggingEvent.getMessage().toString()
,"Hello Test");
}
public static class TestAppender extends AppenderSkeleton{
public List<LoggingEvent> events = new ArrayList<LoggingEvent>();
public void close() {}
public boolean requiresLayout() {return false;}
@Override
protected void append(LoggingEvent event) {
events.add(event);
}
}
public static class ClassUnderTest {
private static final Logger LOGGER =
Logger.getLogger(ClassUnderTest.class);
public static void logMessage(){
LOGGER.info("Hello Test");
LOGGER.debug("Hello Test");
}
}
}
Run Code Online (Sandbox Code Playgroud)
log4j.properties
log4j.rootCategory=INFO, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d %p [%c] - %m%n
# un-comment this will fail the test
#log4j.logger.com.haim.logging=DEBUG
Run Code Online (Sandbox Code Playgroud)
Aaron解决方案的另一种选择是配置带有附加StringWriter的WriterAppender.在测试结束时,您可以验证日志输出字符串的内容.
这样更容易实现(不需要自定义代码),但是在检查结果方面不太灵活,因为您只能将输出作为纯文本.在某些情况下,与Aaron的解决方案相比,验证输出更加困难.
| 归档时间: |
|
| 查看次数: |
53503 次 |
| 最近记录: |