2011-04-13 18 views
7

JUnit (test 3 ve 4 stili karışımı) ile test edilen bir Java projem var, test edilen sınıflar bir log4j hatası kaydedebilir. Böyle bir hata kaydedilirse birim testi başarısız olur.Log4j hatası() çağrıları jUnit testlerinde istisna atar?

çalışma zamanı istisnası bir log4j hatasına herhangi bir çağrı test altındaki kodu() yöntemi yapmak ve bu nedenle testi başarısız olmasına log4j veya birim test altyapısını ya yapılandırmak için genel bir yolu var mı? AOP bir yol olabilir, ama başka olasılıklarla da ilgileniyorum.

Buradaki amaç, log4j error() öğesinin yanlış kullanıldığı yerlerde kodun ayıklanmasıdır. Yani, bir hata günlüğe kaydedilir, ancak bir istisna veya hata işleme gerçekleşmediğinde, ya gerçekten bir hata değildir, ya da yükseltilmelidir.

örn:

public class MyTest extends TestCase { 
    public void testLogAnError() { 
     // Want to make this fail 
     new MyClass().logAnError(); 
    } 
} 

public class MyClass() { 
    static Logger logger = Logger.getLogger("foo"); 

    public void logAnError() { 
     // I'm logging an error, but not doing anything about it 
     logger.error("Something bad, or is it?"); 
     // TODO throw an exception or don't log an error if there isn't one 
    } 
} 

Güncelleme: Bu kullanıyorum çözüm şu anda böyle görünüyor. Bu sbridges' cevabına göre (test sınıfa eklendi):

Sonra
private static final Appender crashAndBurnAppender = new NullAppender() { 
    public void doAppend(LoggingEvent event) { 
     if(event.getLevel() == Level.ERROR) { 
       throw new AssertionError("logged at error:" + event.getMessage()); 
     } 
    } 
}; 

setUp içinde:

Logger.getRootLogger().addAppender(crashAndBurnAppender); 

ve ayırma:

Logger.getRootLogger().removeAppender(crashAndBurnAppender); 

cevap

14

Sen atar yeni Appender oluşturabilir Hata seviyesinde oturum açtığınızda bir AssertionError.

şey gibi, testte

class TestAppender extends AppenderSkeleton { 
    public void doAppend(LoggingEvent event) { 
     if(event.getLevel() == Level.Error) { 
       throw new AssertionError("logged at error:" + event.getMessage()); 
     } 
    } 
} 

yapın

Logger.getRootLogger().addAppender(new TestAppender()); 

Düzenleme: Ralph belirttiği gibi Testi bitirdikten sonra, TestAppender kaldırın.

+2

Testten sonra 'Logger.getRootLogger(). AddAppender (yeni TestAppender()); Logger statik olduğundan, bu eklenti de kaldırılmazsa bir sonraki testte de yayınlanacak! - Bunu bir '@ '' Yönteminde veya son ifadede yapmalısınız, çünkü testinizdeki" normal "kod istisnadan sonra yürütülmeyecektir. – Ralph

+0

Parlak! Böyle bir şeyim var ve kaçıyor ... – Rog

0

Log4j2 çözüm

Sadece bu tökezledi ama Log4j sürümünü 2 kullanıyorum çünkü ben kodu uyarlamak zorunda kaldı. Kaynakların çoğu, konfigürasyon fabrikaları, konfigüratörler, logger içerikleri ve her neyse, kafa karıştırıcı karmaşadan kaynaklanıyordu. Yaptığım şey en temiz veya resmi yol olmayabilir, ancak basit.

iki kamu statik yöntemlerle böyle bir yarar sınıfının

Tanımı: Bir @AfterClass yönteme içinde

private static Appender appender; 

private static void enableThrowOnLog(Level level) { 
    // Downcast: log4j.Logger -> log4j.core.Logger 
    Logger rootLogger = (Logger) LogManager.getRootLogger(); 

    appender = new ThrowingAppender(level); 
    appender.start(); 
    rootLogger.addAppender(appender); 
} 

public static void disableThrowOnLog() { 
    // Downcast: log4j.Logger -> log4j.core.Logger 
    Logger rootLogger = (Logger) LogManager.getRootLogger(); 

    appender.stop(); 
    rootLogger.removeAppender(appender); 
    appender = null; 
} 

private static class ThrowingAppender extends AbstractAppender { 
    private final Level level; 

    public ThrowingAppender(Level level) { 
     // Last parameter: ignoreExceptions -- must be false or exceptions will be swallowed 
     super("ThrowingAppender", new AbstractFilter() {}, PatternLayout.createDefaultLayout(), false); 
     this.level = level; 
    } 

    @Override 
    public synchronized void append(LogEvent event) { 
     Level eventLevel = event.getLevel(); 
     if (eventLevel.isMoreSpecificThan(this.level)) { 
      String message = event.getMessage().getFormattedMessage(); 
      throw new AppenderLoggingException(eventLevel + " level was logged:\n> " + message); 
     } 
    } 
} 
İdeal olarak bir JUnit 4 @BeforeClass yöntemi içinde enableThrowOnLog() diyoruz

ve disableThrowOnLog(), böylece küresel günlüğüne değişiklikler Sistem uygun şekilde geri alınmamıştır.