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");
}
}
4 comments:
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
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.
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.
Post a Comment