如何使用 junit 测试是否使用 log4j 记录了警告?

2022-08-31 17:36:39

我正在测试一种方法,该方法在出现问题时记录警告并返回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;

我想用 junit 测试一下,除了返回 null 之外,在所有情况下(例如,找不到文件,文件是只读的),是否发出了警告。
任何想法?
谢谢,阿萨夫:-)


更新

我对亚伦的回答的实现(加上彼得的言论):

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);
}

谢谢你们,


答案 1

在单元测试的设置中:

  1. 获取相同的记录器
  2. 使其无添加剂
  3. 添加一个追加器,用于记住列表中的消息:

    public class TestAppender extends AppenderSkeleton {
        public List<String> messages = new ArrayList<String>();
    
        public void doAppend(LoggingEvent event) {
            messages.add( event.getMessage().toString() );
        }
    }
    
  4. 将追加器添加到记录器

现在,您可以调用代码。测试后,您将在列表中找到所有日志消息。如果需要,请添加日志级别 ()。messages.add( event.getLevel() + " " + event.getMessage() );

在 中,再次删除追加器并启用可加性。tearDown()


答案 2

使用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());
  }
}

推荐