13

Consider the following sample C# Data Transfer Object (DTO):

public class MailingAddress
{
   public string StreetAddress {get; set;}

   public string City {get; set;}

   public string StateOrTerritory {get; set;}

   public string PostalCode {get; set;}
}

I can write unit tests to check for someone setting the various string members to null or empty strings. I could also make the setters private on all the fields so that it has to be constructed via a constructor.

I'm asking about this because the CodeCoverage tool is reporting 0% on all these DTO methods and I'm trying to figure out if there's some reasonable testing I might do here.

I have googled a bit and not come up with a lot. I also searched here but haven't found anything that seems to address this. If I've missed something please link it in the comments.

EDIT:

Someone helpfully suggested that my question might be answered by this question. The thing is that while it doesn't look like there's code being run for the various fields, there is, in fact default code there.

It wouldn't be a case of testing the language features. If someone modifies the default behavior of the get/set pairs then I should have unit tests around them to insure they still behave as expected.

Onorio Catenacci
  • 2,977
  • 3
  • 28
  • 38

5 Answers5

33

This class is just a holder of data. It doesn't have any behavior to test. So, no, do not write test cases for this class.

However, your application should have functions that take an instance of this class as an argument. When writing test cases for those functions, you should be using a real instance of this data class. Since there is no behavior, you don't have to worry about external dependencies that might have side-effects. Using a real instance of the class instead of a test double will cause the lines of this class covered by the test suite.

8

These days, I'm with Jon on this. But I used to be part of the "no tests" camp in the past.

I think this is one of those many situations where there are no right or wrong answers; only trade-offs. You should educate yourself about the cons and pros and choose to join a camp. Your future experience might motivate you to switch. Anyway, let's get technical.

In a broader sense than covering DTOs, what we're discussing here is to decide whether we need to cover getters (/setters) or not.

I'd first like to refer you to Roy Osherove's book, The Art of Unit Testing where it goes:

"Properties (getters/setters) are good examples of code that usually doesn’t contain any logic and so doesn’t require specific targeting by the tests. It’s code that will probably get used by the unit of work you’re testing, but there’s no need to test it directly. But watch out: once you add any check inside a property, you’ll want to make sure that logic is being tested."

Then I'd like to partially quote Paul Bourdeaux's stand from his blog writeup and refer you to read the examples there as it all doesn't fit here.

"Should we test getters and setters?” The answer, in the humble opinion of this engineer, is yes.

Let’s face it, public getter and setter methods are (normally) inherently simple, and writing unit tests for them seem to be a waste of time – testing the language’s ability to set and pass variables instead of any actual code. But there are a few dangers lurking in not testing them...

The easiest way that I know of to break [getter/setter] code is by changing existing code without understanding the full ramifications of doing so. Testing getters and setters also guards against regression bugs. Here is an example of a simple getter"

Bottom line is, they must be tested. The question is directly or indirectly. Choose your club!

sepehr
  • 181
5

For completeness, you could write tests for these. This would cover the code. If anyone changed a getter/setter in the future, a test would fail and they would have to update the test(s).

The tests would be very trivial at this point since there is no defined behavior. They would be worth very little, since all they are doing is updating the backing private field. But your coverage would be 100% and if anyone changed behavior a test would fail.

Tests should have value.

Let's say your setter changed to (pseudo-code):

set { if value != null 
      { name = value }; 
    } 

In the case, there is behavior present. Having test(s) in this scenario would add value.

sergiol
  • 157
Jon Raynor
  • 11,773
2

Time has moved on…

Records were not available when your question was written, but they have been available since Nov 2021…and where possible you should be using records for your dto’s as they more clearly convey your intent (no behavior, even on properties).

With records, it’s clear you shouldn’t have unit tests, as there is nothing to test other than the compiler…

jmoreno
  • 11,238
-2

One quick approach that gets some coverage is:

            //Arrange
            var dto = new T();
        //Act
        var result = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(dto));

        //Assert
        result.Should().NotBeNull();

For complete coverage, build out the json to be deserialized.