【Unity】internalなクラスのテストを書く

Unityでinternalなクラスのテストを書く方法をまとめました。

Unity2020.1

internalなクラスのテスト?

C#にはinternalという修飾子が存在します。
これをクラスに付けるとそのアセンブリ内でのみ参照できるクラスを作ることができます。

internal class Example
{
}

上記のように書くとこのExampleクラスは他のアセンブリから参照することができません。
それ自体は問題ないのですが、テストは別アセンブリとして定義されるため、
Exampleクラスのテストを書きたいときに困ってしまいます。

そこで本記事では、internalなクラスのテストを書く方法を紹介します。

なおUnityにおけるテストの仕方については触れませんが、
以下の記事にまとめていますので必要に応じて参照してください。

light11.hatenadiary.com

internalなクラスのテストを書く

まず適当にテストするためのプロパティをExampleクラスに定義しておきます。

internal class Example
{
    public int Value => 100;
}

次にテスト用のアセンブリ(asmdefファイル)をInternalTest.Testsという名前で作っておきます。

f:id:halya_11:20200802150231p:plain
テスト用アセンブリ設定

次にExampleクラスのasmdefファイルと同じ位置に以下のようなcsファイルを作成します。

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("InternalTest.Tests")]

このInternalsVisibleToアトリビュートを指定すると現在のアセンブリのinternalなクラスを指定したアセンブリに公開することができます。

docs.microsoft.com

この状態でテストを記述してみます。

using NUnit.Framework;

public class InternalTest
{
    [Test]
    public void TestExample()
    {
        Assert.That(new Example().Value, Is.EqualTo(100));
    }
}

正常にテストが作成され、成功することが確認できました。

f:id:halya_11:20200802150721p:plain
テスト成功

独立したcsファイルを作る必要もない

なお上記ではInternalsVisibleToを定義するために独立したcsファイルを作成していましたが、
関連するクラスに直接記述してしまうのも手かとおもいます。

参考までに、UnityのAddressablesのResourceManagerでは以下のようにResourceManagerにテスト用のInternalsVisibleToが記述されています。

[assembly: InternalsVisibleTo("Unity.ResourceManager.Tests")]
[assembly: InternalsVisibleTo("Unity.Addressables.Tests")]
[assembly: InternalsVisibleTo("Unity.Addressables")]
#if UNITY_EDITOR
[assembly: InternalsVisibleTo("Unity.Addressables.Editor")]
#endif

namespace UnityEngine.ResourceManagement
{
    /// <summary>
    /// Entry point for ResourceManager API
    /// </summary>
    public class ResourceManager : IDisposable
    {
        ...(略)...
    }
}

関連

light11.hatenadiary.com

参考

docs.microsoft.com