2015-05-05 31 views
12

當運行單元測試時,我想在測試錯誤級別消息的過程中失敗。使用SLF4J/Logback實現這個最簡單的方法是什麼?我想避免編寫自己的ILoggerFactory實現。在錯誤級別日誌事件中使Logback引發異常

我試過編寫一個自定義的Appender,但是我不能通過調用Appender的代碼來傳播異常,Appender的所有異常都會被抓到。

回答

0

因此,如果調用記錄器的任何錯誤報告消息,您希望失敗測試用例。

  1. 使用依賴關係注入將要測試的代碼與應該使用的記錄器相關聯。
  2. 實現一個實現SLF4J記錄器接口的測試double,它對大多數方法不做任何處理,但爲錯誤記錄方法拋出AssertionError。
  3. 在測試用例的設置部分,注入測試用例。
0

記錄框架通常設計爲不會向用戶拋出任何異常。另一種選擇(除了Raedwald的回答)將創建一個自定義appender,當記錄ERROR消息時將靜態布爾標誌設置爲true,在安裝方法中重置此標誌並在拆卸方法中檢查它(或者創建JUnit規則重置/檢查標誌)。

4

關鍵是寫一個自定義的appender。你不會說你使用了哪個單元測試框架,但是對於JUnit我需要做類似的事情(它比一切錯誤稍微複雜一點,但基本上是相同的概念),並且創建了一個JUnit @Rule來添加我的appender ,並且appender根據需要未通過測試。

我把我的代碼,這個答案在公共領域:

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.LoggerContext; 
import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.AppenderBase; 
import org.junit.rules.ExternalResource; 
import org.slf4j.LoggerFactory; 
import static org.junit.Assert.fail; 

/** 
* A JUnit {@link org.junit.Rule} which attaches itself to Logback, and fails the test if an error is logged. 
* Designed for use in some tests, as if the system would log an error, that indicates that something 
* went wrong, even though the error was correctly caught and logged. 
*/ 
public class FailOnErrorLogged extends ExternalResource { 

    private FailOnErrorAppender appender; 

    @Override 
    protected void before() throws Throwable { 
     super.before(); 
     final LoggerContext loggerContext = (LoggerContext)(LoggerFactory.getILoggerFactory()); 
     final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)); 
     appender = new FailOnErrorAppender(); 
     appender.setContext(loggerContext); 
     appender.start(); 
     rootLogger.addAppender(appender); 
    } 

    @Override 
    protected void after() { 
     appender.stop(); 
     final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)); 
     rootLogger.detachAppender(appender); 
     super.after(); 
    } 

    private static class FailOnErrorAppender extends AppenderBase<ILoggingEvent> { 
     @Override 
     protected void append(final ILoggingEvent eventObject) { 
      if (eventObject.getLevel().isGreaterOrEqual(Level.ERROR)) { 
       fail("Error logged: " + eventObject.getFormattedMessage()); 
      } 
     } 
    } 
} 

用法的例子:

import org.junit.Rule; 
import org.junit.Test; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class ExampleTest { 
    private static final Logger log = LoggerFactory.getLogger(ExampleTest.class); 

    @Rule 
    public FailOnErrorLogged failOnErrorLogged = new FailOnErrorLogged(); 

    @Test 
    public void testError() { 
     log.error("Test Error"); 
    } 

    @Test 
    public void testInfo() { 
     log.info("Test Info"); 
    } 
} 

的方法是testError失敗並testInfo方法傳遞。如果測試調用記錄錯誤的真正測試類,它的工作原理也是一樣的。