Coding Tips – Testing exceptions

coding-tip

Welcome to my new series entitled “Coding Tips”. The purpose of this new collection of articles is to share some tips related to programming I came across during my journey. These tips helped me and I still use some of them and maybe it can help you too.

If you are the same kind of developer as I am, you certainly like to write unit tests and a lot of them. You certainly also want to test every aspect of your code, including exceptions. But you might wonder if there is an easy way to test them, and of course there is !

Given the following (only for testing purpose) sample of code in C# :

public static class ClassToTest
{
    public static bool IsAQuestion(string toTest)
    {
        return toTest.EndsWith("?");
    }
}

The following call will throw a NullReferenceException :

ClassToTest.IsAQuestion(null);

So ? How to test this assertion ? Here is a common solution :

[TestMethod]
public void TryCatchTest()
{
    try
    {
        ClassToTest.IsAQuestion(null);
    }
    catch (NullReferenceException)
    {
        return;
    }
    Assert.Fail();
}

This test will pass only if a NullReferenceException is catched, otherwise it fails.

This solution looks a bit “heavy” for just testing an exception and this is why there is another solution much “lighter” than can be used. Please welcome the ExpectedExceptionAttribute :

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void AttributeTest()
{
    ClassToTest.IsAQuestion(null);
}

Yes, this is it, nothing more ! You can now test the exceptions with a single line of code. The .NET framework is full of helpful classes, the ExpectedExceptionAttribute is one of them but sometimes finding them is harder than using them.

If you use a different testing framework than Microsoft.VisualStudio.QualityTools.UnitTestFramework, it is likely that there is also a functionality allowing you to easily check the exceptions.

I hope you will like this new “Coding Tips” series, do not hesitate to share your ideas in order to improve it.

See you next time !

Keep control of your entities

Today I want to share tips to improve the control you have over your code and especially over your entities in a Oriented Object language. The example will be in C# .NET.

During my (still short) career I’ve been  working on a certain amount of projects and I often found the same practices related to entities : they are just PODS !

Here’s an example with an Invoice, a Product and a Customer entities.

public class Product
{
    public UInt16 Id { get; set; }
    public string Name { get; set; }
}
 
public class Customer
{
    public string Name { get; set; }
}
 
public class Invoice
{
    public Product Product { get; set; }
    public Customer Customer { get; set; }
 
    public void DisplayInfo()
    {
        Console.WriteLine("{0} ordered :", Customer.Name);
        Console.WriteLine("{0} - {1}", Product.Id, Product.Name);
    }
}

Now, let’s use these classes in a program :

class Program
{
    static void Main(string[] args)
    {
        Invoice invoice = new Invoice();
        invoice.DisplayInfo();
    }
}

And yes, this program throws a NullReferenceException when displaying the invoice because my Invoice.Customer instance is NULL. Let’s fix our Invoice class the following way.

public class Invoice
{
    public Invoice()
    {
        Product = new Product();
        Customer = new Customer();
    }
 
    public Product Product { get; set; }
    public Customer Customer { get; set; }
 
    public void DisplayInfo()
    {
        Console.WriteLine("{0} ordered :", Customer.Name);
        Console.WriteLine("{0} - {1}", Product.Id, Product.Name);
    }
}

But this time the program class looks like this :

class Program
{
    static void Main(string[] args)
    {
        Invoice invoice = new Invoice();
        invoice.Customer = null;
        invoice.DisplayInfo();
    }
}

The NullReferenceException still occurs because the Customer is set to NULL. I know you wonder why I did this… Because the code structure allows me to do it ! It might look stupid this way but sometimes in a more complex application you can set an object’s property to NULL without knowing it, if you’re calling an external service for example or another provider.

Let’s change our Invoice class again to use a bit of encapsulation.

public class Invoice
{
    public Invoice(Product product, Customer customer)
    {
        Product = product;
        Customer = customer;
    }
 
    public Product Product { get; protected set; }
    public Customer Customer { get; protected set; }
 
    public void DisplayInfo()
    {
        Console.WriteLine("{0} ordered :", Customer.Name);
        Console.WriteLine("{0} - {1}", Product.Id, Product.Name);
    }
}

With this version the Customer and the Product have to be set when constructing the Invoice. So ? Do you think we’re done ? Let’s find out with a new program.

class Program
{
    static void Main(string[] args)
    {
        Invoice invoice = new Invoice(null, null);
        invoice.DisplayInfo();
    }
}

Still not running correctly, still the same exception for the exact same reason. You can add control to your entities properties but you should add control during initialization as well to avoid manipulating an invalid instance of your class.

This lead us to our final version of the Invoice class (at least in this post).

public class Invoice
{
    public Invoice(Product product, Customer customer)
    {
        if (product == null)
            throw new ArgumentNullException("product");
        if (customer == null)
            throw new ArgumentNullException("customer");
 
        Product = product;
        Customer = customer;
    }
 
    public Product Product { get; protected set; }
    public Customer Customer { get; protected set; }
 
    public void DisplayInfo()
    {
        Console.WriteLine("{0} ordered :", Customer.Name);
        Console.WriteLine("{0} - {1}", Product.Id, Product.Name);
    }
}

I choose to use the ArgumentNullException to prevent the construction of an invalid object. This allow me to have a complete control on my Invoice entity. With these kind of practices I try to prevent incorrect behavior from misuse. I transformed a PODS into an entity with “intelligence”.

I hope these tips will help you and do not hesitate to share yours and/or to comment about these tips.

See you next time for more software development related topics !