Related link: http://www.agiledeveloper.com/download.aspx

Where does your unit test go?

Test Driven Development and Test First Development have a number of benefits. It is more of an act of design than an act of verification as I have discussed in a three part series at http://www.agiledeveloper.com/articles/TDDPartI.pdf.

Where should the tests go? While writing test cases, you may have to access not only the public members, but also internal or package friendly members as well. In Java, you would want to write your test cases in the same package. In the case of .NET, you would put them in the same project. If you do not want to deploy the test cases, you can exclude them from your release build.

What if you need to test a private method or property of a class? First question to ask is, why would you want to test such methods or properties? Generally speaking, may be not. However, say I am writing an Order class and as part of its checkout method, I need to charge a credit card. The method to charge the credit card most likely is going to be private as it is an implementation and not something that the Order class would expose as public.

Why test it? You would certainly want to make sure you have handled the failure cases well. What if the card was invalid, or the charge did not go though or even you could not communicate with the service that authorized the credit card.

How do you test private methods in this case? Before I get into that, let me say that I am not suggesting that you write all your test cases like this. I would use this as an exception than a norm.

Why not write your test case that needs to test your private methods as an inner class in Java and nested class in .NET. Let’s try that.

Here is the .NET example:

	public class Order
	{
		private string Charge(Card theCard, double amount)
		{ //...
			return "chargeCode...";
		}

		[TestFixture]
		public class OrderChargeTest
		{
			private Order theOrder;
			private Card theCard;
			private double AMOUNT1 = 121.12;

			[SetUp]
			public void SetUp()
			{
				theOrder = new Order();
				theCard = new Card(...);
			}

			public void TestCharge()
			{
				theOrder.Charge(theCard, AMOUNT1);
			}
		}
	}

You can write more test to make sure the code behaves well for failure of the Charge.

Here is the Java code that does the same thing as above:

public class Order
{
    private String Charge(Card theCard, double amount)
    { //...
        return "chargeCode...";
    }

    public class OrderChargeTest extends TestCase
    {
        private Order theOrder;
        private Card theCard;
        private double AMOUNT1 = 121.12;

        public void setUp()
        {
            theOrder = new Order();
            theCard = new Card(...);
        }

        public void TestCharge()
        {
            theOrder.Charge(theCard, AMOUNT1);
        }
    }
}

In addition, I have a TestIt class as shown below:

public class TestIt
{
    public static void main(String[] args)
    {
        junit.swingui.TestRunner.run(Order.OrderChargeTest.class);
    }
}

When I run JUnit, I get the following error:

junit.framework.AssertionFailedError: Class Order$OrderChargeTest has no public constructor TestCase(String name) or TestCase()

The reason for this error is inner classes in Java are special. The constructor of the inner class is synthesized with a reference to the host class (the class in which it is contained). As a result, JUnit is complaining that it could not find a constructor which takes no arguments. Of the four types of inner classes (regular, local, anonymous and static) only the static inner class’ constructor is not synthesized with a reference to the host class. In Java, we should use static inner class instead of regular inner class here.

Modifying the code as

public class Order
{
    private String Charge(Card theCard, double amount)
    { //...
        return "chargeCode...";
    }

    public static class OrderChargeTest extends TestCase
    {
        private Order theOrder;
        private Card theCard;
        private double AMOUNT1 = 121.12;

        public void setUp()
        {
            theOrder = new Order();
            theCard = new Card(...);
        }

        public void TestCharge()
        {
            theOrder.Charge(theCard, AMOUNT1);
        }
    }
}

takes care of the problem.

On rare occasions, writing your test cases as nested classes in .NET or static inner classes in Java may come in handy. One down side is it is hard to exclude these from the release build. In the next version of .NET, with the introduction of partial classes, that should not be a problem.

What are your thoughts on TDD/TFC and where tests should go