今回は C# で Moq でモックを使ったテストをする最低限の要素をメモします。
■ テストプロジェクトの作成
コマンドで作成できます。
今回は NUnit で進めていこうと思うので、NUnit プロジェクトを作成します。プロジェクト名は SampleTestProject としてみます。
dotnet new nunit -n SampleTestProject
もし、MSTest が良ければこうです。
dotnet new mstest -n SampleTestProject
Visual Studio でも作れます。
コマンドと Visual Studio の違い
コマンドで作ったプロジェクトと Visual Studio で作ったプロジェクトでは最初に作られているテストクラスのコードに大きな違いがあります。
次の前者が dotnet コマンド、後者が Visual Studio です。なんと! Visual Studio ではファイルスコープの名前空間が使われていません。これはほんの少しの手間ですが直すのに手間がかかります。素直に dotnet コマンドで作るのがよさそうです。
using NUnit.Framework; namespace SampleTestProject; public class Tests { [SetUp] public void Setup() { } [Test] public void Test1() { Assert.Pass(); } }
using NUnit.Framework; namespace SampleTestProject { public class Tests { [SetUp] public void Setup() { } [Test] public void Test1() { Assert.Pass(); } } }
■ Moq のインストール
テスト用モックライブラリの Moq は NuGet からインストールします。
cd SampleTestProject dotnet add package Moq
Visual Studio の GUI でもインストールできます。
■ テストコード例
== モックを作るインターフェイス
interface ISample { // モックを作るメソッド int SampleMethod(int value); }
== テスト対象のクラス。このクラス単体のテストを行うためには、依存している ISample のモックが必要
class TestableClass { public int TestableMethod(ISample sample) { // 依存している ISample のメソッドを 2 回呼んでいる。2 回目の結果を return している var value = sample.SampleMethod(0); return sample.SampleMethod(value); } }
== テストクラス。この記事の本体
using NUnit.Framework; using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] namespace SampleTestProject; public class Tests { [SetUp] public void Setup() { } [Test] public void Test1() { // モックを準備 Moq.Mock<ISample> moq = new Moq.Mock<ISample>(); // モックメソッド。0 という引数で呼ばれたときは 10 を return する。10 という引数では 11 を return moq.Setup(x => x.SampleMethod(0)).Returns(10); moq.Setup(x => x.SampleMethod(10)).Returns(11); // モックのオブジェクトを取得 ISample mock = moq.Object; // テストを実行 TestableClass testableClass = new(); var value = testableClass.TestableMethod(mock); // テスト結果検証 Assert.AreEqual(value, 11); // モックメソッドが 0 という引数では 1 回呼ばれていれば OK moq.Verify(x => x.SampleMethod(0), Moq.Times.Once); // モックメソッドが 10 という引数では 1 回呼ばれていれば OK moq.Verify(x => x.SampleMethod(10), Moq.Times.Once); } }
■ InternalsVisibleTo
テストを行う際はだいたいはプロダクトのプロジェクトで Internals になっているクラスをテストする機会があると思います。その場合、プロダクトのプロジェクトで InternalsVisibleTo の設定をします。
プロダクトのプロジェクトに InternalVisibleTos.cs といった名前でファイルを追加します。
using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("{テストプロジェクト名}")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
もし InternalsVisibleTo の設定がないと
エラー CS0122 'XXXXXXXX' はアクセスできない保護レベルになっています
や
"Can not create proxy for type XXXXXXXXXX because it is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo(\"DynamicProxyGenAssembly2\")] attribute, because assembly XXXXXXXXXX is not strong-named."} Castle.DynamicProxy.Generators.GeneratorException
といったエラーが出ます。
簡単ですね。