Handling Dependent Expected Results

Recently the question came up as to how to handle creating expected results for a unit test when those results rely on a call to an outside helper function. As an example, in our current project we have a “Name” class that has methods for creating a string that is formattted to be first name then last name and another function to create a string that is last name comma first name. The name class looks a little bit like the below example:

public class Name
{
    public string FirstName
    { get; set; }

    public string LastName
    { get; set; }

    public string GetFirstNameLastName()
    {
        return this.FirstName + " " + this.LastName;
    }

    public string GetLastNameFirstName()
    {
        return this.LastName + ", " + this.FirstName;
    }
   
}

The question that arose was what to do in tests where some expected result had been manipulated by a helper method, such as one of the name formatting methods in our “Name” class. For instance, let say we had a report class that created one row per customer wtih some information about that customer. The first field of the report is supposed to be the customers name formatted as last name comma first name. In the code we’re using the the ‘ GetLastNameFirstName()’ method of the name object to get the string the report class is printing. Let’s say the report has a ‘ReportDataSource’ that takes a Customer object that has ‘Name’ property called customer name and sets a string ‘Name’ as such: (Below is not real just for example sake)

public class ReportDataSource
{
    public string Name;

    public void FillItem(Customer customer)
    {
        this.Name = customer.CustomerName.GetLastNameFirstName();

     }
}

Let’s say we have a unit test for this that looks like the below, the gist of the question is what should we set as the ‘excpectedName’? (Below test would be overkill itself in reality, again just for exlanatory purposes)

 [Test]
public void GetCustomerName()
{
    //--Arrange

    string expectedName = "";

    Customer cust= new Customer();
    cust.CustomerName.FirstName = "first";
    cust.CustomerName.LastName = "Last";
    
    
    ReportDataSource reportData = new ReportDataSource();

    //--Act
    reportData.FillItem(cust);

    //--Assert
    Assert.AreEqual(expectedName, reportData.Name);
}

We came up with three possiblities, we could hardcode the value so we’d have a line that looked like the below:

string expectedName = "Last, First";

Hard coding seemed fine and makes the test very explicit. The worry for some was what happened if we changed the behavior of the ‘GetLastNameFirstName()’ method? Then we would have to go manually change all the places where we’d hard coded what we expected it to do.

I agreed this was a concern, but my thinking was from a testing perspective we weren’t concerned with how the method did it’s work, we wanted to see that exactly that hard coded string was returned in our test given the input we’d provided. Someone pointed out that this wasn’t necessarily the case, we did not really want to test for our hard coded string since we wanted to rely on the Name class, and we did want any changes there to not break out test. The entire reason for centralizing name formatting was so changes in name formatting would only have to be made in one place. I had to agree.

The next thought if we wanted to make sure the Name object was involved was to mock the Name object.  This sounded like a good idea, we want to rely on the Name object and wanted our test not to break if the Name object changes it’s behavior.  However, as I thought about this it started to seem like overkill. To easily mock the Name object we’d have to extract an interface and go through the extra effort of creating and programming a mock in testing to isolate the behavior of a method that just turns around a name?

I could see this being necessary if the method did something that wasn’t repeatable.  Lets say in our method we were creating a GUID, well we’d have no idea what each new GUID would be, we’d have to mock the call to create our GUID if we wanted to test any output that contained the GUID.  Every call to the “GetLastNameFirstName()’ method will produce the exact same output given the same input.   Which lead me to the solution I liked best.

Given that the ‘GetLastNameFirstName()’ method will produce the expected result we want, and if it’s behavior changes we want to expect the new behavior, why not use the method itself to create our expected result?  Something like this:

[Test]
        public void GetCustomerName()
        {
            //--Arrange

           
            Customer cust= new Customer();
            cust.CustomerName.FirstName = "first";
            cust.CustomerName.LastName = "Last";
            
            //-- use the dependent method to create the test data since we don't want
            //   to test the dependent method just want to make sure we're always consistend with it
            string expectedName = cust.CustomerName.GetLastNameFirstName();
            
            ReportDataSource reportData = new ReportDataSource();

            //--Act
            reportData.FillItem(cust);

            //--Assert
            Assert.AreEqual(expectedName, reportData.Name);
        }

Some still preferred the idea of mocking, but this worked best for me. If the method is deterministic and doesn’t rely on anything outside the immediate application domain, why not let the method act as it’s own mock? This allowed us to not be dependent on the behavior of the methods in the Name class as any changes cause changes in our expected results. We also can avoid the extra effort for mocking. I like it!

Leave a Reply

Your email address will not be published. Required fields are marked *