2017-03-06 16 views
4

私はモデルクラスに情報を記録したいと思います。単体テストの目的ではなく、デバッグしようとしている現実のシナリオのために必要です。私はJUnitテストの実行時に、私は次のエラーを取得android.util.Logメソッドを使用しようとした場合Android JUnitテストのログを処理する方法は?

しかし、私はこれが発生する理由を理解

java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details. 

を、私はモデルクラスにAndroidのフレームワークのコードを使用してはならないことフレームワークに依存しないように設計されています。私は実際にエラーに反対して論争しているのではなく、むしろこれを回避する方法を見つけようとしています。

私には1つのアイデアがありますが、これは意味がありますか?

これらの線に沿ってCustomLogクラスを作成します(...などE、D、メソッド)​​は、ログ機能を実行するために必要なメソッドとのインターフェースである

public class CustomLog { 
    private static ILogger mLogger; 

    public static void setLogger(ILogger logger) { 
     mLogger = logger; 
    } 

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

I android.util.Logメソッドを使用するILoggerImplと、System.out.printlnに出力するだけのMockLoggerクラスを作成できます。また、何もしません。

私のニーズに完全に合っていると思います(ライフサイクルの早い段階で私のCustomLogクラスをセットアップする必要がありますが、それは大きな問題ではありません)。

しかし、サードパーティのライブラリ/外部コードをモデルクラスに追加する必要があった場合は、新しいライブラリ/コードでandroid.util.Logメソッドを使用すると、同じ方法で再度破損する可能性があります。

だから、私が使うことができる「すべてを捕まえる」という振る舞いはありますか?どう思いますか?

+0

'System.out.println()'は完全ではないかもしれませんが、テスト出力に現れます。 – zsmb13

+0

間違いなく。私はここで説明しました: "私は' android.util.Log'メソッドを使う 'ILoggerImpl'と、単に' System.out.println'に出力したり、何もしない 'MockLogger'クラスを作ることができました。他に何か!)。" - 私の質問は、これがうまく動作するように_how_に関係しています。 'System.out.println'は単体テストですが、' android.util.Log'はデバッグ/リリースの非単体テストです! – Zach

+1

ああ、申し訳ありません。私はあなたが本当にできる最高のものを見つけたと思う。 – zsmb13

答えて

0

あなたが引用した「嘲笑されない」例外を解決する1つの方法は、use PowerMockito to mock the Logging methodsです。代わりに、リンクの答えで説明したようPowerMockito.mockStatic(Log.class);を呼び出すので、あなたはthisからインスピレーションを取り、代わりにSystem.out.printlnを実行する方法でreplace()Android.utilさんLog.vLog.dLog.i & Log.eにPowerMockitoを使用することができます。これにより、Android Studioの[実行]ウィンドウに記録されたメッセージを確認することができます。

String[] logMethods = {"v", "d", "i", "e"}; 
InvocationHandler systemOutPrintln = new InvocationHandler() { 
    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     StringBuilder messageBuilder = new StringBuilder(); 
     for (int i = 0; i < args.length; i++) { 
      String arg = args[i].toString(); 
      messageBuilder.append(arg); 
      // add separators, ASCII art, ... 
     } 
     System.out.println(messageBuilder); 
     return messageBuilder.toString().length(); 
    } 
}; 

for (String logMethod : logMethods) { 
    replace(method(Log.class, logMethod, String.class, String.class)).with(systemOutPrintln); 
    replace(method(Log.class, logMethod, String.class, String.class, Throwable.class)).with(systemOutPrintln); 
} 

免責事項:上記が最も慣用的な実装であるかどうかはわかりません。

+0

個人的には、これは、モデルコードがAndroidの依存関係を持つべきではないという原則に違反していると思いますが、確かにこれは私が思っていることです! – Zach

関連する問題