はじめに
扱っているシステムのオリジナルなログサービスにて、出力するログメッセージ内容をUTでテストする必要がありました。
そのときにC#のモックツールであるmoqを利用。
この記事はその際のまとめメモになります。
【注意】
この記事のコードは、実際のコードを記事用に改変し抽出したものでそのままでは動きません。ご了承ください。
テスト対象コード
ログサービス提供側
モック化対象クラスのコードです。
public class LogService
{
// 利用されるメソッド
public void WriteSystemMessageException(SystemMessageException exception)
{
Write(exception.SystemMessage); // モック化したいメソッド
}
// モック化したいメソッド
public void Write(SystemMessage)
{
WriteCore(SystemMessage); // 実際にログを出力するメソッド
}
}
Writeメソッドで直接ログが出力できますが、SystemMessageExceptionという例外クラス経由でログ出力を行いたいため、WriteSystemMessageExceptionメソッドが用意されています。
今回は、Writeをモック化したいと考えています。
ログサービス利用側
public class ConsumerOfLogService
{
public LogService logService = new LogService();
public void Index()
{
try
{
raiseError(); // SystemMessageExceptionが発生する処理
}
catch (SystemMessageException sme)
{
logService.WriteSystemMessageException(sme); // ログサービスでログを出力
}
}
}
テスト対象のクラスとメソッドです。
SystemMessageException例外クラスにログメッセージが含まれており、このログメッセージをテストコード内で取得したいと考えています。
また、利用側のコードでは、LogServiceクラスのWriteSystemMessageExceptionメソッドのみが利用されており、Writeメソッドは直接利用されていません。
moqでテストを書く
ログメッセージを取得し検証するテストコードを書いていきます。
[TestClass]
public class ConsumerOfLogServiceTests
{
[TestMethod]
public void LogService_test()
{
var mock_Log = new Mock<LogService>() { CallBase = true }; // ①
string logMessage = null; // ログメッセージを格納する変数
mock_Log
.Setup(c => c.Write(It.IsAny<SystemMessage>()))
.Callback<SystemMessage>(sm => logMessage = sm.Message); // ②
ConsumerOfLogService target = new ConsumerOfLogService{ logService = mock_Log.Object };
target.Index(); // テスト対象メソッドを実行
mock_Log.Verify(c => c.Write(It.IsAny<SystemMessage>()), Times.Once()); // モックが実行されたか確認
Assert.AreEqual("期待するログメッセージ", logMessage); // 受け取ったログメッセージで期待値検証する
}
}
ポイントとして2点あります。
ポイント①: CallBase = true で本来の実装を実行させる
①にある、{ CallBase = true }がないと、今回の場合、モック化したWriteが実行されません。なぜなら、moqのデフォルトではモック化していないWriteSystemMessageExceptionは何も処理しない動作となるためです。今回は、WriteメソッドがWriteSystemMessageExceptionメソッドの裏にいます。
そこで、{ CallBase = true }を記述することで、本来のWriteSystemMessageExceptionメソッドの実装のコードを実行され、処理がWriteメソッドまで到達します。
ポイント②: Callbackでモック化したメソッドが受け取る引数を処理する
②のように、MockインスタンスのCallbackメソッドを利用することで、テスト内変数のlogMessageにWriteメソッドが受け取った引数を受取り、処理することができます。
まとめ
moqの機能を利用してオリジナルなログサービスのログメッセージをテストすることができました。