2013-10-17 60 views
6

ロガーはPowermockやロガーを使うオーバーライドされたコンストラクターの助けを借りて嘲笑されています。mockitoを使ってJavaサービスで静的ロガーをモックする方法はありますか

ロガーがコード全体で使用されているため、単にmockitoを使用する簡単な方法ではありませんか?コールを無視するか、模擬する方法 - 私はメッセージを検証する必要はありません。ヌルポインタの例外を避けたいだけです。

私はフレームワークをモックするのが初めてですので、Jmockitを混合してライブラリ - 今のところjomockitを避ける唯一の理由は、パワーがいっぱいで、簡単に誤用される可能性があるということです!

+1

は、なぜあなたはロガーを模擬する必要があります:これは、私はMockito使用してそれを行う方法ですか?ロギングを起こさせないのはなぜですか?ファイルが書き込まれないようにするログのテスト構成を設定することができます(たとえば、すべてのログをコンソールに送信するなど)。 –

+0

うーん、シンプルで優れたアイデア。 – cpandey05

答えて

4

特定のレベルでログすることが非常に重要だと思う場合は、ログの検証を使用します。

ユーティリティクラス

public final class LoggingTestUtil { 

    private LoggingTestUtil() { 
    } 

    public static void setupLoggingMock(Logger logger, Appender<ILoggingEvent> appender) { 
     logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); 
     when(appender.getName()).thenReturn("MOCK"); 
     logger.addAppender(appender); 
    } 

    public static void verifyLogAppended(Appender<ILoggingEvent> appender, final String loggedString) { 
     verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() { 
      @Override 
      public boolean matches(final Object argument) { 
       return ((LoggingEvent) argument).getMessage().contains(loggedString); 
      } 
     })); 
    } 

    public static void verifyLogAppendedAtLevel(Appender<ILoggingEvent> appender, final Level level) { 
     verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() { 
      @Override 
      public boolean matches(final Object argument) { 
       return ((LoggingEvent) argument).getLevel().equals(level); 
      } 
     })); 
    } 

    public static void verifyLogAppendedAtLevel(Appender<ILoggingEvent> appender, final Level level, final String loggedString) { 
     verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() { 
      @Override 
      public boolean matches(final Object argument) { 
       LoggingEvent event = (LoggingEvent) argument; 
       return event.getLevel().equals(level) && event.getMessage().contains(loggedString); 
      } 
     })); 
    } 
} 

をテストクラスでは

private static Logger root; 
@Mock 
private static Appender<ILoggingEvent> mockAppender; // used to test that logging occurs 

    @Test 
    public final void testSomething(){ 
     LoggingTestUtil.setupLoggingMocks(root, mockAppender); 
     underTest.doSomethingBad(); 
     LoggingTestUtil.verifyLogAppendedAtLevel(mockAppender, Level.ERROR, "bad thing"); 
    } 
+3

私はそれが脆弱で過度のものであるので、模擬はログ検証のための貧弱な戦略だと信じています。 log4jのデフォルトロガーに一時的なアペンダーを追加するJUnitルールを作成しました。これにより、ルールをテストに追加するだけでロギングの検証が可能になります。 https://github.com/dancerjohn/LibEx/blob/master/testlibex/src/main/java/org/libex/test/logging/log4j/Log4jCapturer.java –

+0

@JohnB - 興味深い...チェックアウトします。レベル/文字列が変更されたときに壊れるので、私はこの解決策が脆弱であることを知ります。しかし、その点でルールはまったく同じではないでしょうか?過剰なことは、モックがはるかに重くなることを意味しますか?私は嘲笑することに比較的新しいので、知りたいと思っています。 :) – Dennis

+0

1.はい、モックははるかに重量があり、予想されるメソッド呼び出しを設定する必要があります。 2.ロギングレベルが検証の一部であった場合のみ、テストは失敗します。エラーメッセージが表示され、失敗した場合はINFOでした。任意のレベルでメッセージを期待するなら、それは失敗しません。 –

関連する問題