How to Unit Test a Private/Protected Method with MSTEST

Note: these steps work for both private and protected methods

Search online or post this question on Stack Overflow and guess what you will get in response most of the time.  

Don’t do it, I repeat Do not unit test private methods

These are 3 of common responses I found online as to why you should not unit test private methods.

  • You should only unit test public methods, treat public methods as a public api into your class.
  • If a class in developed correctly you will never have to write a test for a public method.
  • Private methods are details for the class object and can come under heavy changes

For move information on this here is a great article:

So now that the fluff above is done, like myself, there might be a situation were you really want to Unit Test that private method.  In my mind you debug through private methods with breakpoints to verify the code is doing what it should, why not write a unit test for it.  I personally would not write a unit test for every private method (that would be just insane and violate the Single Responsibility Principle.  I have also had friends tell me they were asked this during an interview.  My guess is to verify their level of knowledge of MSTEST.

Here is method we want to test.  The initial demo is from a video I watched by Peter Provost at TechEd Europe introducing Shims.  The method will check today’s date and throw an exception is today is Y2K.  If you don’t know what that is, I have just gotten really old.

private void CheckIfEndOfWorld()
{
    if (DateTime.Now == new DateTime(2000, 1, 1))
    {
        throw new Y2KException();
    }
}

First thing we do is create our unit test method, since we are checking for an exception we add that to the method as well.

[TestMethod]
[ExpectedException(typeof(Y2KException))]
public void EndOfWorldCheckerPrivTest()
{
    
}

Since we are using a shim to fake out the date (because we want to actually have the exception thrown) we need to wrap it in a user statement.

TestMethod] [ExpectedException(typeof(Y2KException))] public void EndOfWorldCheckerPrivTest() { // scope the shim otherwise it will fail,

// this is so it does not last forever. using (ShimsContext.Create()) { } }

Next we create an instance of the class and use it with an instance of PrivateObject.  This allows us to invoke a private method in the class.

[TestMethod] [ExpectedException(typeof(Y2KException))] public void EndOfWorldCheckerPrivTest() { // scope the shim otherwise it will fail,

// this is so it does not last forever. using (ShimsContext.Create()) { AsyncExamples asyncEx = new AsyncExamples(); PrivateObject y2K = new PrivateObject(asyncEx); } }

Finally we setup our Shim and tell it that today is January 1st 2000.  Then invoke our private method.   Once that is done, run the test, and the exception will be thrown.

[TestMethod] [ExpectedException(typeof(Y2KException))] public void EndOfWorldCheckerPrivTest() { // scope the shim otherwise it will fail,

// this is so it does not last forever. using (ShimsContext.Create()) { AsyncExamples asyncEx = new AsyncExamples(); PrivateObject y2K = new PrivateObject(asyncEx); ShimDateTime.NowGet = () => new DateTime(2000, 1, 1); y2K.Invoke("CheckIfEndOfWorld"); } }

Advertisement
This entry was posted in C# and tagged . Bookmark the permalink.