2016-02-22 35 views
7

AndroidスタジオでJUnit(メソッド)テストを実行しているときにLogcat(Log.i、Log.d)メッセージを出力する方法はありますか?Androidスタジオjunitテストのログメッセージ

System.out.printメッセージが表示されますが、logcatの出力はありません。

実行コンフィギュレーション(AndroidスタジオのGUIウィンドウ)にはAndroidテストでのテスト用のlogcatオプションがありますが、JUnitテスト用ではありません。

これはどういうことですか?何かヒントありがとう!

+0

あなたはそれを行う方法を見つけましたか?私は今同じ質問に直面しています... –

+1

@IgorGanapolsky、 – Vasiliy

答えて

0

私はこの同じことを探していて、まっすぐ答えを見つけたことはありませんでした。私はこの質問が1年以上前だと知っていますが、それでも将来の参考のためにここに答えがあるのは良いことです。

android.util.Logクラスは、ローカルJVMで単体テストを実行するときに、Logcatに直接ログを記録し、android.util.Logの実装は使用できません。ユニットテストでLogクラスを使用しようとするとエラーが発生します。「ユニットテストを実行するために使用されるandroid.jarファイルには実際のコードは含まれていません(これらのAPIはデバイス上のAndroidシステムイメージによってのみ提供されます) "
See Android Documentation on Unit Testing

したがって、実際にandroid.util.Logを使用するには、ローカルでモックし、System.out.printを使用してコンソールに印刷する必要があります。まず、プロジェクトにPowerMockitoを追加します。あなたはGradleのを使用している場合は、あなただけの次の依存関係を追加することができます。

testCompile 'junit:junit:4.12' 
testCompile 'org.powermock:powermock:1.6.5' 
testCompile 'org.powermock:powermock-module-junit4:1.6.5' 
testCompile 'org.powermock:powermock-api-mockito:1.6.5' 

次は私がMockitoを使ってモックオブジェクトに渡されたパラメータを返す方法を見つけ出すためにスティーブの答えhereを使用しました。これは、誰かを助け

import android.util.Log; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.invocation.InvocationOnMock; 
import org.mockito.stubbing.Answer; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

import static org.mockito.Matchers.anyString; 
import static org.powermock.api.mockito.PowerMockito.when; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Log.class}) 
public class SomeUnitTest { 

    @Test 
    public void testSomething() { 
     System.out.println("Running test"); 
     PowerMockito.mockStatic(Log.class); 

     // Log warnings to the console   
     when(Log.w(anyString(), anyString())).thenAnswer(new Answer<Void>()  { 
      @Override 
      public Void answer(InvocationOnMock invocation) throws Throwable { 
       Object[] args = invocation.getArguments(); 
       if (args.length > 1) { //cause I'm paranoid 
        System.out.println("Tag:" + args[0] + " Msg: " + args[1]); 
       } 
       return null; 
      } 
     }); 
     Log.w("My Tag", "This is a warning"); 
    } 
} 

希望:

結果は次のようなものでした!

+0

以下の私の答えを見ることができます。希望の動作を達成するために、標準のOOPプラクティスを使用してください。 – Vasiliy

+0

"私は避けるように勧めますPowerMockをどうにかして " - 大丈夫、どうしてあなたはその理由を説明するのですか? – user3474985

+0

私が言ったように: "望ましい動作を達成するために標準的なOOPプラクティスを使用する"。バイトコードへの「ハッキング」は簡単な解決策のように見えるかもしれませんが、そうではありません。この経路は非常に厄介です。これを正しく行う方法の詳細については、私の回答 – Vasiliy

3

LogcatはAndroid機能であるため、ユニットテストではログ出力が表示されません.JUnitテストでは標準Javaのみしか使用できないため、Android機能は動作しません。

ユニットテストでは、テストされたコンポーネントに「テスト倍精度」を挿入できます。しかし、Log.xコールは静的なので、コールを無効にすることはできません(例えば、PowerMockには解決しないでください。

したがって、最初のステップは、Log.x通話のためのプロキシとして動作します非静的クラスを導入することになります。

/** 
* This class is a non-static logger 
*/ 
public class Logger { 

    public void e(String tag, String message) { 
     Log.e(tag, message); 
    } 

    public void w(String tag, String message) { 
     Log.w(tag, message); 
    } 

    public void v(String tag, String message) { 
     Log.v(tag, message); 
    } 

    public void d(String tag, String message) { 
     Log.d(tag, message); 
    } 
} 

は、あなたが今Log.x電話を持っているすべての場所で、このクラスを使用します。

第二段階は、標準出力にリダイレクトLoggerの試験二重実装を作成することであろう。

public class UnitTestLogger extends Logger{ 

    @Override 
    public void e(String tag, String message) { 
     System.out.println("E " + tag + ": " + message); 
    } 

    // similar for other methods 
} 

最後のステップは、ユニットテストでUnitTestLogger代わりのLoggerを注入することである。

@RunWith(MockitoJUnitRunner.class) 
public class SomeClassTest { 

    private Logger mLogger = new UnitTestLogger(); 

    private SomeClass SUT; 

    @Before 
    public void setup() throws Exception { 
     SUT = new SomeClass(/* other dependencies here */ mLogger); 
    } 

} 

OOPの概念について厳密に厳密にしたい場合は、LoggerUnitTestLoggerの共通インターフェイスを抽出できます。

つまり、ユニットテストでLog.xコールを調べる必要はありませんでした。私はあなたがそれを必要としないと思う。

コードは、If:あなたは

一般的なアドバイス...デバッグモードでユニットテストを実行し、コードの上にライン・バイ・ラインlogcat出力を調査しようとするよりもはるかに高速であるデバッガ、中をステップ実行することができますテストにはLog.xスタティックコールが含まれており、ユニットテストはクラッシュしません。問題があります。

私はすべてのテストがRobolectricで実行されているか、build.gradle:unitTests.returnDefaultValues = trueでこの文が実行されていると思います。

Robolectricですべてのテストを実行すると不安定ですが、すべてのAndroid呼び出しがデフォルト値を返す場合、テストスイートは信頼できません。私はあなたが将来的にあなたをかみ合わせてくれるので、さらに進める前にこの問題を修正することをお勧めします。

+0

を参照してください。単にLogoggerではなく、Loggerインスタンスのログに名前を付けるだけで、Log呼び出しを変更する必要はありません。 – JulianSymes

関連する問題