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();
}
}