2

I'd like to do a unit test for my private methods in C#. Since the methods are private, they are not accessible from the test environment.

Nalara
  • 101
  • 1
  • 7
  • 1
    You could probably use [Reflection](https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/reflection) – derHugo Nov 14 '19 at 07:49

2 Answers2

3

I figured out to do it this way:

  1. Go to C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies\ and copy the file Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll to a folder in your Unity project.
  2. Reference the file in your .asmdef file, which you find in the "Tests" folder: inspector view
  3. In your c# test script, you now can access this adding using Microsoft.VisualStudio.TestTools.UnitTesting;
  4. Instantiate an instance of your class containing the method to test and create a private object as well. In case the method you want to test is static, create a private type instead:
    public class MyClass
    {
        private static int AddOne(int i)
        {
            return i += 1;
        }
        private int SubOne(int i)
        {
            return i -= 1;
        }
    }

    MyClass myClass = new MyClass();
    PrivateType privateTypeMyClass = new PrivateType(myClass.GetType());
    int res1 = (int)privateTypeMyClass .InvokeStatic("AddOne", 2);
    PrivateObject privateObjectMyClass = new PrivateObject(myClass);
    int res2 = (int)privateObjectMyClass.Invoke("AddOne", 2);
  1. If you want to pass more than one argument, you can use an obj[] to pass these.
GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
Nalara
  • 101
  • 1
  • 7
0

It is not suggested to write unit tests for private methods. You should write tests only and only for the public methods because a caller interacts with your class only through public methods and properties. In the flow, private methods get called by the public methods. So write your tests such that they call the public methods and covers private methods via different flows. This way you will also be able to know if there are some unused private methods in your code which can be deleted.

Yogi
  • 9,174
  • 2
  • 46
  • 61
  • So, what is the point of a Unit test if you cannot test the private fields since most of them are private? It seems useless and requires extra lines of code to write in each class to get the values. I would simply use the "Debug.log("message");" – Talha Safdar Mar 12 '23 at 15:07
  • I used your approach to run some tests on private methods. After some time when I rerun the tests they started throwing some exceptions. It turns out as the code developed, I added some more functionality that required more rigorous scene set ups despite that I haven't touched the actually tested code. So this approach is a non-trivial way to test a trivial code and requires constant update to the testing code. In a scenario where we can easily test a private method, we would delete or update the test code only if the tested code itself has changed or deleted – WVrock Jul 23 '23 at 06:50
  • 1
    @WVrock I have not suggested any approach for testing private methods. Because it goes against the principles. Probably you commented and downvoted on other answer :) – Yogi Jul 25 '23 at 07:52