テストダブルを簡単に作れるライブラリ「Moq」をUnityで使う手順です
Moq 4.20.72
Unity 2022.3.28f1
Moqとは?
Moq を使うと、インターフェースを実装したテストダブルを簡単に作成することができます。
本来は以下のようにインターフェースを実装したテストダブルクラスをいちいち作らなければいけないところを・・
using Moq; using NUnit.Framework; public sealed class ExampleTest { public class MockService : IService { public string Name => "MockService"; public int GetValue() { return 5; } } [Test] public void GetMultipliedValue_UsingMockService() { var service = new MockService(); var example = new Example(service); var multipliedValue = example.GetMultipliedValue(); Assert.That(multipliedValue, Is.EqualTo(10)); } }
以下のようにテストダブルクラスを実装することなくテストを書くことができます。
using Moq; using NUnit.Framework; public sealed class ExampleTest { [Test] public void GetMultipliedValue() { // インターフェースが実装されたモック(を管理するオブジェクト)を作成 var serviceMock = new Mock<IService>(); // GetValue メソッドが 5 を返すようにモックを設定 serviceMock.Setup(x => x.GetValue()).Returns(5); var example = new Example(serviceMock.Object); // Object プロパティを使用してテストダブルを取得 var multipliedValue = example.GetMultipliedValue(); Assert.That(multipliedValue, Is.EqualTo(10)); } }
本記事ではこの Moq を Unity で使う方法についてまとめます。
インストール
Moq は NuGet に公開されているので、DLL の形で Unity にインストールする必要があります。
NuGet for Unity などでインストールしてもいいと思いますが、今回は直接DLLを入れていきます。
まず、Moq とその依存ライブラリは以下の通りです。
DLL をダウンロードするには、まず NuGet のページ右下の Open in NuGet Package Explorer をクリックします。

フォルダ構造が表示されるので、netstandard2.0 以下にあるDLLをダブルクリックしてダウンロードします。

他のライブラリについても同様の手順でダウンロードできます。
次に、ダウンロードしたDLLをUnityの適当なフォルダにインポートします。
テストでしか使わないものなので、インポート設定は以下のように、Auto Reference を外して、Define Constraints に UNITY_INCLUDE_TESTS を設定しておきます。

テスト用アセンブリをセットアップ
次にテスト用のアセンブリをセットアップします。
アセンブリ自体の作り方は割愛しますが、以下の記事にまとめていますので必要に応じて参照してください。
アセンブリを作成したら、Assembly References に Moq.dll を加えます。

テスト対象のアセンブリとスクリプトを作成
セットアップが完了したら、次にテスト対象のアセンブリとスクリプトを適当に作成しておきます。
今回は以下のスクリプトを作成しました。
public interface IService { string Name { get; } int GetValue(); } public class FooService : IService { public string Name => "FooService"; public int GetValue() { return 123; } } public class Example { private readonly IService _service; public Example(IService service) { _service = service; } public string GetServiceName() { return _service.Name; } public int GetMultipliedValue() { return _service.GetValue() * 2; } }
なお、Internal なものをテストする際には InternalsVisibleTo アトリビュートにテスト用のアセンブリ名を指定します。
が、Moq を使う場合にはさらに DynamicProxyGenAssembly2 も指定する必要があるので、internal なものをテストする際には忘れないようにしてください(忘れてもエラーで気づけます)。
using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Example.Tests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // Moqのために必要
テストを作成する
次に、前節で作ったセンブリをテスト用のアセンブリの Assembly Definition Reference に追加しつつテストを書いていきます。
using Moq; using NUnit.Framework; public sealed class ExampleTest { [Test] public void GetServiceName() { // インターフェースが実装されたモック(を管理するオブジェクト)を作成 var serviceMock = new Mock<IService>(); // Name プロパティが「MockService」という値を返すようにモックを設定 serviceMock.SetupGet(x => x.Name).Returns("MockService"); var example = new Example(serviceMock.Object); // Object プロパティを使用してテストダブルを取得 var serviceName = example.GetServiceName(); Assert.That(serviceName, Is.EqualTo("MockService")); } [Test] public void GetMultipliedValue() { var serviceMock = new Mock<IService>(); // GetValue メソッドが 5 を返すようにモックを設定 serviceMock.Setup(x => x.GetValue()).Returns(5); var example = new Example(serviceMock.Object); var multipliedValue = example.GetMultipliedValue(); Assert.That(multipliedValue, Is.EqualTo(10)); } }
FooService という実装クラスを使うことなく、インターフェースを通したテストをモックオブジェクトを使ってできることが確認できました。
その他の使い方
その他の使い方については公式のドキュメントがわかりやすいので本記事では説明しません。
必要に応じて以下を参照してください。