Unity のUnitTestでprivate な関数をテストしたい場合

  • ブックマーク

例えば、よくあるエディタ拡張でメニュー呼び出し関数を作った時は以下のようになると思います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class MyEditor {

    [MenuItem("MyTools/MyEditorFunc")]
    private static void MyFunc()
    {
        Debug.Log("Done");
    }
}

まあ関数はpublicでもprivateでもいいのですが、たまたまprivateになっている場合があるとします。

すると、

public class MyEditorTest {

    [Test]
    public void CreateCubeUploadTestPasses()
    {
        MyEditor.MyFunc(); // ←コンパイルエラー
    }
}

当たり前ですが、ユニットテストを作る時に呼び出せなくてコンパイルエラーになってしまいます。

「テストだけのために元のソースコードを変更するのもなー」

と考えるのがテスト実装担当の人情というものでしょう。
テスト実装は自分の庭をいくらでも汚しても良いけど、人の庭は絶対に手をつけてはいけないという不文律があるからです(嘘)

というわけで、private関数をテストするために、今回は Reflection を使います。

using UnityEngine;
using UnityEditor;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;
using System.Reflection;

public class MyEditorTest {

    [Test]
    public void CreateCubeUploadTestPasses()
    {
        //MyEditor.MyFunc(); // を呼び出す代わりに...
        System.Type myClass = typeof(MyEditor);
        UnityEngine.Assertions.Assert.IsNotNull(myClass);
        MethodInfo myMethod = myClass.GetMethod("MyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        UnityEngine.Assertions.Assert.IsNotNull(myMethod);
        myMethod.Invoke(this, null);
        //  :
        // なんらかのチェック
        //  :
    }
}

こんな感じにすれば、自分の庭(テストコード)を汚しても、人の庭(テスト元)を汚さない、ことができるということです。