Vadim's Weblog

Never stop learning.

Testing Non-Public members with MbUnit

Posted by Vadim on April 10, 2007

MbUnit Test Framework allows you to test non-public members of a class. You can test private, protected, internal, and of course protected internal members. Members can be fields, properties, and methods.

Let’s create MyClass with non-public members:


public class MyClass
{
  private string _field = "Private";

  private string PrivateProperty
  {
    get { return _field; }
  }

  private string GetHello()
  {
    return "Hello";
  }

  private int PrivateAdd(int x, int y)
  {
    return x + y;
  }

  protected double PrivateAdd(double x, double y)
  {
    return x + y;
  }
}

As you can see we have one private field, one private property, two private methods, and one protected. Two PrivateAdd methods were created to show that you can test overloaded methods.

First, let’s create MyClassTests class that will test MyClass. In order to use MbUnit Framework, we need to add reference to MbUnit.Framework.dll.
Also we need to add reference to MbUnit.Framework.2.0.dll. The later one has Reflector class that we’re going to use to test private and protected members.

We have a choice of using static methods of Reflector class or create an instance of Reflector. I’m personally not a big fan of static methods. Currently using static methods you can test only non-public fields and methods without arguments. If some people would like to be able to test properties and methods with arguments using static methods, just let MbUnit community know and the will be happy to add it for you.
One more thing: if a name of a member incorrect, an exception is thrown with a similar message:

Fail to find NoExisit Method in MyClass.MyClass.

Well, enough talking here’s the fixture:


[TestFixture]
public class MyClassTests
{
  Reflector _reflector;

  [TestFixtureSetUp]
  public void FixtureInit()
  {
    MyClass myClass = new MyClass();
    _reflector = new Reflector(myClass);
  }

  [Test]
  public void PrivateField_Test()
  {
    Assert.AreEqual("Private"
      ,_reflector.GetNonPublicField("_field"));
  }

  [Test]
  public void Static_PrivateField_Test()
  {
    Assert.AreEqual("Private"
      , Reflector.GetNonPublicVariable(new MyClass(), "_field"));
  }
  
  [Test]
  public void PrivateProperty_Test()
  {
    Assert.AreEqual("Private"
      , _reflector.GetNonPublicProperty("PrivateProperty"));
  }

  [Test]
  public void PrivateMethodNoArguments_Test()
  {
    Assert.AreEqual("Hello"
      , _reflector.RunPrivateMethod("GetHello"));
  }

  [Test]
  public void Static_PrivateMethodNoArguments_Test()
  {
    Assert.AreEqual("Hello"
      , Reflector.RunNonPublicMethod(new MyClass(), "GetHello"));
  }

  [Test]
  public void PrivateMethod_Test()
  {
    Assert.AreEqual(5
      , _reflector.RunPrivateMethod("PrivateAdd", 2, 3));
  }

  [Test]
  public void ProtectedMethod_Test()
  {
    Assert.AreEqual(5.6
      , _reflector.RunPrivateMethod("PrivateAdd", 3.5, 2.1));
  }

  [Test]
  [ExpectedException(typeof(ApplicationException))]
  public void NonExstingMethod_Test()
  {
     _reflector.RunPrivateMethod("NoExisit");
  }
}

Advertisements

4 Responses to “Testing Non-Public members with MbUnit”

  1. Anonymous said

    Vadim,

    It is great to see you are blogging. You must be the person I know since you have the same first name and the same passion for MbUnit! :)

    I am not sure about testing private methods – this seems very kewl but also would worry me about the design of the class. If it is doing enough that it needs to be independently tested, then it should probably be a public method in another class.

    Best regards,
    Jonathan Cogley
    http://weblogs.asp.net/jcogley

  2. Vadim said

    Jonathan,

    I’m the person you think I am. It’s nice to hear from you. I completely agree with you. I myself used this functionality only in demo tests. However, in my company people reluctant to write unit tests (you probably noticed that when you were here). I extended MbUnit with testing non-public member functionality because I had an ultimatum: if people cannot test private methods they are not going to write unit tests. I’m trying to convert them slowly. You know that to write TESTABLE code people need to change the way they code.

    Saying that, I believe that sometimes to test legacy code, you might want write a test for a private method. I also plan to extend it, so our security team can write tests for protected classes. As you know sometimes for security reasons you want to have some non-public classes.

  3. .NetKicks said

    Hi vadim,
    a nice tutorial about the different possibilities about testing private and protected methods can be found here:
    http://www.codeproject.com/csharp/TestNonPublicMembers.asp
    Maybe that’s also interessting for you.

  4. Shellie said

    It’s an awesome post in support of all the internet users; they will obtain advantage from it I am sure.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: