Help us understand the problem. What is going on with this article?

NSubstitute チートシート

More than 1 year has passed since last update.

NSubstitute とは

ユニットテストで利用することを想定した、.NET Framework 向けのMockライブラリ。
元となるインターフェースやクラスからテストで利用するためのモックオブジェクトを作成する。

公式サイト: http://nsubstitute.github.io/
利用バージョン: NSubstitute-1.4.3.0

チートシート

生成

  • interfaceからモック生成
    var calculator = Substitute.For<ICalculator>();

  • 実クラスからモック生成 (仮想メンバのみをモック化。それ以外は実際に実行される)
    var calculator = Substitute.For<CalculatorClass>();

挙動を設定

  • 戻り値設定
    calculator.Add(1, 1).ReturnsForAnyArgs(99);

  • 戻り値設定 (特定引数)
    calculator.Add(1, 2).Returns(3);

  • 処理呼び出し
    calculator.Add(1, 1).ReturnsForAnyArgs(x => Console.Log("called."));

  • 1回目は10, 2回目は20を返す
    calculator.Add(1, 1).ReturnsForAnyArgs(10, 20);

呼び出し結果確認

以下を実行すると、確認結果が正しくなかったときにReceivedCallsExceptionが発生。

  • 呼び出されたことを確認
    calculator.ReceivedWithAnyArgs().Add(1, 1);

  • 呼び出されたことを確認 (特定引数)
    calculator.Received().Add(1, 2);

  • 呼び出された回数確認
    calculator.ReceivedWithAnyArgs(3).Add(1, 1);

  • プロパティが呼び出されたことを確認
    var dummy = calculator.Received().prop; // getter
    calculator.Received().prop = "hoge"; // setter

  • 呼び出し状態クリア
    calculator.ClearReceivedCalls();

(付録) unityでの利用方法

以下URLからdllのバイナリを取得
https://github.com/nsubstitute/NSubstitute/downloads

(解凍フォルダ)\lib\NET35\NSubstitute.dll
……をunityの"Assets/Plugins"以下へコピー

エディタで NSubstitute.dll を選択し、ExcludePlatformsのEditor以外のチェックをONにしておく

以下のようなC#ファイルを作成してTestRunnerで実行

using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using NSubstitute;

public interface ISample {
    int Hoge();
}

public class NSubstituteTest {
    [Test]
    public void SubstituteTest() {
        var mockSample = Substitute.For<ISample>();
        mockSample.Hoge().Returns(99);

        Assert.AreEqual(99, mockSample.Hoge());
    }
}

(付録) サンプルコード

using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using NSubstitute;

// モック作成元のインターフェース
public interface ISample {
    int Hoge();
    int Fuga(int n);
    int hogeProp { get; set; }
}

public class NSubstituteTest {
    // 挙動を設定
    [Test]
    public void Returns() {
        // モックの作成
        var mockSample = Substitute.For<ISample>();

        // 戻り値設定
        mockSample.Hoge().ReturnsForAnyArgs(99);
        Assert.AreEqual(99, mockSample.Hoge());

        // 戻り値設定 (特定引数)
        mockSample.Fuga(0).Returns(99);
        Assert.AreEqual(99, mockSample.Fuga(0));

        // 処理呼び出し
        mockSample.Fuga(2).Returns(n => { Debug.Log("called."); return 0; });
        mockSample.Fuga(2);

        // 1回目は10, 2回目は20を返す
        mockSample.Fuga(1).Returns(10, 20);
        Assert.AreEqual(10, mockSample.Fuga(1));
        Assert.AreEqual(20, mockSample.Fuga(1));
    }

    // 呼び出し結果確認
    [Test]
    public void Received() {
        // モックの作成
        var mockSample = Substitute.For<ISample>();

        // 呼び出されたことを確認
        mockSample.Hoge();
        mockSample.ReceivedWithAnyArgs().Hoge();

        // 呼び出されたことを確認  (特定引数)
        mockSample.Fuga(1);
        mockSample.Received().Fuga(1);
        mockSample.DidNotReceive().Fuga(2);

        // 呼び出された回数確認
        mockSample.ReceivedWithAnyArgs(1).Fuga(1);
        mockSample.Fuga(9);
        mockSample.Fuga(9);
        mockSample.ReceivedWithAnyArgs(3).Fuga(1);

        // プロパティが呼び出されたことを確認
        var dummy = mockSample.DidNotReceive().hogeProp;
        dummy = mockSample.hogeProp;
        dummy = mockSample.Received().hogeProp;

        mockSample.DidNotReceive().hogeProp = 1;
        mockSample.hogeProp = 1;
        mockSample.Received().hogeProp = 1;

        // 呼び出し状態クリア
        mockSample.ClearReceivedCalls();
        mockSample.Received(0).Hoge();
    }
}
culage
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした