Geeks With Blogs
Abhishek Anand Bits & Bytes about .net technology framework.
Before we proceed any further, I should say this, Testing through this public API should be your first choice.

Alternative for Abstract Base Classes

One common case is when an abstract base class defines functionality in some protected methods, and there are a series of inheriting classes using those methods without overriding them. In this case, rather than choosing one inheriting member at random to test the methods, you can simply create a “Fake” class locally in your test project that inherits from the base class. This “Fake” could then expose the protected members in some public members of its own; and your tests would run against the “Fake” class.

 

The following is a simplified example of how to create a “Fake” object for this purpose:

 

         public abstract class MyBaseClass<T>

    {

         protected string MyProtectedMethod()

         {

             return typeof(T).ToString();

         }

    }

    internal class FakeClass : MyBaseClass<Int32>

    {

         public string CallMyProtectedMember()

         {

             return base.MyProtectedMethod();

         }

    }
       …

   [TestMethod]

   public void TestMyProtectedMember()

   {

       FakeClass fake = new FakeClass();

       string retVal = fake.CallMyProtectedMember();

       Assert.AreEqual(retVal, "System.Int32");

   }


Alternative using PrivateObject

When necessary, the PrivateObject class can be used to expose non-public members to your unit tests. The class uses reflection to access the members based on a string identifier. The following is an example of how to test the private method above using PrivateObject. 


Note: the example is NOT a case where PrivateObject should be used, instead this is meant to show the simplest usage for the PrivateObject class.

 

[TestMethod()]

        public void GetStringArgIsOneTest()

        {

            //Arrange

            var myClass = new MyClass();

            var privObj = new PrivateObject(myClass);

            //Act

            object retVal = privObj.Invoke("GetString", new []{typeof(Int32)}, new object[]{1});

            //Assert

            Assert.AreEqual(retVal.ToString(), "Hello World");

        }


Unit Testing Private Static Methods

You cannot access static methods with the PrivateObject class. Instead of the PrivateObject class, you should use the PrivateType class. You can think of PrivateObject as being an object, containing only instance methods while PrivateType is a type which is how you would call static methods.

 

Example:

PrivateType privateType = new PrivateType(typeof(SomeClass));

       var actual = privateType.InvokeStatic("SomeStaticMethod", 1);

actual.Should().Be(expected);

Posted on Wednesday, November 20, 2013 4:03 PM .net , unit testing , c# , privateobject | Back to top


Comments on this post: Unit Testing Non-Public Methods

# re: Unit Testing Non-Public Methods
Requesting Gravatar...
Works well for testing private C# methods. Thank You.
Howver, I am looking to do the same thing in C++.
Is that possible?
Thanks in advance
Left by Michael Yanowitz on Mar 01, 2014 1:53 AM

Your comment:
 (will show your gravatar)


Copyright © Abhishek Anand | Powered by: GeeksWithBlogs.net