私はテスト可能なコードを書く際に読んでいましたが、現在私のロギングフレームワークAPIをリファクタリングして実践しています。私の主な関心事は、1)ビジネスコードからの呼び出しが容易であること、2)簡単な疑似コードなので、実際のロギングを呼び出さずにビジネスコードをテストできること、そしてロギングされたかどうかを主張できることですそのテスト。正しい方法でJavaでモック可能なロギングAPIを構築する
私はかなりテスト可能と感じるところに達しましたが、私はまだ改善できると感じています。私と一緒に抱きしめてください。これは私がこれまで持っていたものです。
/*
* The public API, which has a mockable internal factory responsible for creating log implementations.
*/
public final class LoggerManager {
private static LoggerFactory internalFactory;
private LoggerManager() {}
public static SecurityLogger getSecurityLogger() {
return getLoggerFactory().getSecurityLogger();
}
public static SystemErrorLogger getSystemErrorLogger() {
return getLoggerFactory().getSystemErrorLogger();
}
private static LoggerFactory getLoggerFactory() {
if (internalFactory == null)
internalFactory = new LoggerFactoryImpl();
return internalFactory;
}
public static void setLoggerFactory(LoggerFactory aLoggerFactory) {
internalFactory = aLoggerFactory;
}
}
/*
* Factory interface with methods for getting all types of loggers.
*/
public interface LoggerFactory {
public SecurityLogger getSecurityLogger();
public SystemErrorLogger getSystemErrorLogger();
// ... 10 additional log types
}
public final class LoggerFactoryImpl implements LoggerFactory {
private final SecurityLogger securityLogger = new SecurityLoggerImpl();
private final SystemErrorLogger systemErrorLogger = new SystemErrorLoggerImpl();
public SecurityLogger getSecurityLogger() {
return securityLogger;
}
public SystemErrorLogger getSystemErrorLogger() {
return systemErrorLogger;
}
}
APIは、ビジネスコードでこのように呼ばれている:
LoggerManager.getSystemErrorLogger().log("My really serious error");
私はその後、TestLoggerFactoryを使用してユニットテストでこれをあざけるだろう、単純にすべてのロギングコールとなりますを追跡し、テスト・ロガーを作成しますそれは例えばassertNoSystemErrorLogs()を実行することが可能に:
LoggerManager.setLoggerFactory(new TestLoggerFactory());
さて、これは正常に動作しますが、私は何かが欠けてるかのように私はまだ落ち、それはより多くのテストが優しい行うことができます。たとえば、静的なsetLoggerFactoryを使用することによって、すべてのテストでロガーファクトリを設定します。つまり、あるテストが実際に別のテストに影響を与えることができます。ですから私の大きな疑問は、この種の簡単に模倣できるAPIを作成する標準的な方法は何ですか?ある種の依存性注入?
疑問点は、アクセスしやすく、使いやすいAPIを作成することと関連があります。私の例がロギングフレームワークAPIであるという事実は、その要点の横にあります。
JUnitテストを行っている場合は、私自身の模擬クラスを実装する代わりに、Mockitoのような模擬フレームワークを使用することを検討します。 Java EE環境では、静的ファクトリを使用する代わりに、修飾子/プロデューサでCDIを使用して異なるロガーを注入することもできます。 – Dainesch
そして私は最初の答えに同意します。すべてのプログラマーはロギングフレームワークを自分自身で作成したいと思っていますが、既に存在するホイールを再発明する時間を費やしています。そして、あなたの車輪のバージョンは独自のもので、洗練されていなくて、テストされたものはそれほど多くありません。もちろん、それは少ない機能を持つでしょう。 – GhostCat
@Dainesch確かに、単体テストでは新しいTestLoggerFactory()の代わりにMockito.mock(LoggerFactory.class)を使うことができましたが、実際にはAPIの設計は変わりません。 – yzfr1