19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

moqで モック化したメソッドが受けとる引数を処理 + 本来の実装を動かす

Last updated at Posted at 2017-07-17

はじめに

扱っているシステムのオリジナルなログサービスにて、出力するログメッセージ内容をUTでテストする必要がありました。

そのときにC#のモックツールであるmoqを利用。

この記事はその際のまとめメモになります。

【注意】
この記事のコードは、実際のコードを記事用に改変し抽出したものでそのままでは動きません。ご了承ください。

テスト対象コード

ログサービス提供側

モック化対象クラスのコードです。

LogService.cs
public class LogService
{
    // 利用されるメソッド
    public void WriteSystemMessageException(SystemMessageException exception)
    {
        Write(exception.SystemMessage);  // モック化したいメソッド
    }

    // モック化したいメソッド
    public void Write(SystemMessage)
    {
        WriteCore(SystemMessage);  // 実際にログを出力するメソッド
    }
}

Writeメソッドで直接ログが出力できますが、SystemMessageExceptionという例外クラス経由でログ出力を行いたいため、WriteSystemMessageExceptionメソッドが用意されています。

今回は、Writeをモック化したいと考えています。

ログサービス利用側

ConsumerOfLogService.cs
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でテストを書く

ログメッセージを取得し検証するテストコードを書いていきます。

ConsumerOfLogServiceTests.cs
[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メソッドを利用することで、テスト内変数のlogMessageWriteメソッドが受け取った引数を受取り、処理することができます。

まとめ

moqの機能を利用してオリジナルなログサービスのログメッセージをテストすることができました。

参考

19
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?