データを取得する MVC コントローラーで使用されるインターフェイスがあります。シンプルにするために、これまでのインターフェイスは次のようになります。
public interface IDataProvider
{
DataModel GetData();
}
アクションで呼び出されるこのインターフェイスの適切な単体テストがあります。ただし、実際の実装では、これはもちろん例外をスローする可能性のある Web サービスを呼び出します。そのため、エラーが発生した場合にメッセージをログに記録するようにテストを記述したいと考えています。
これを行うために、実際にはILoggerと呼ばれるNLogへのインターフェースであるロガーインターフェースがあります。私はこれを行うことができます:
public interface IDataProvider
{
DataModel GetData(ILogger logger);
}
これにより、ロガーの単体テストを実行して、素晴らしくシンプルにすることができます。ただし、ロガーはこの方法とはまったく関係がないため、これが正しい方法だとは思いません。また、ロギングが必要なこのインターフェースに他のメソッドを追加し始めると、それらすべてのメソッドのパラメーターにもロガーを含める必要があります。
今考えられる最善の方法は、実装のコンストラクターにロガーを含めることです。これは次のようになります。
public class DataProvider : IDataProvider
{
private readonly ILogger _logger;
public DataProvider(ILogger logger)
{
_logger = logger;
}
public DataModel GetData()
{
// CODE GOES HERE
}
}
ただし、これは、単体テストでロガーをテストできないことを意味します。ロガーをメソッドから分離してテスト可能にするために、これを達成する最良の方法は何ですか?
どんな助けにも感謝します、ありがとう。
編集:
ここでユニットテストコードを見逃したことに気づきました。
現時点では、GetData が次のようにアクションで呼び出されるようにしています。
var controller = new DataController(_dataProvider.Object);
controller.Index();
_dataProvider.Verify(dataProvider => dataProvider.GetData());
私がやりたいことは同じですが、ロガーの場合ですが、次のように例外がスローされた場合のみです:
_dataProvider.Setup(dataProvider => dataProvider.GetData()).Throws<WebException>();
var controller = new DataController(_dataProvider.Object);
controller.Index();
_logger.Verify(logger => logger.ErrorException(It.IsAny<string>(), It.IsAny<Exception>());
明らかに、ロガーはセットアップでデータプロバイダーに提供されます。それがもう少し理にかなっていることを願っています。