views:

375

answers:

5

Hey there,

I want that my unit tests to cover my POCO's.

How should I test them?

What If I add a new property? How to make my test fail?

Testing the properties and methods I know, but the problem is, how to make sure my tests fail is anything is added to my poco's.

Cordially,

+1  A: 

If you want to add a new feature to the class, write a test that fails because the feature has not been implemented, then implement the feature and see the test pass.

Or...

Run code-coverage metrics as part of the build. They will indicate if code gas been added without being covered by the tests.

Or...

Run mutation tests as part of the build. They will indicate if any tests that cover the code are just running through it and not actually testing anything.

Or all of the above.

Nat
+4  A: 

Testing is about verifying whether what is written is able to do what it should do, nothing more, nothing less. So if you write some code, you do that for a reason. Your tests should reflect that the code indeed matches the reason you wrote the code for. That's it, there's nothing else. I.o.w.: if you write a bunch of classes, you should test whether the behavior you've written indeed is correct compared to what the behavior should do.

Frans Bouma
+3  A: 

From the reading of your question, you either misunderstand what a POCO is, or you misunderstand unit testing.

A POCO is just an old fashioned object. It has state and behavior. You unit test the state by putting (setting) values in to the properties, and asserting that the value is what you expected. You unit test behavior by asserting expectations against methods.

Here would be an oversimplified example of a POCO and its tests. Notice that there's more test code than implementation code. When unit testing is done right (TDD), this is the case.

public class Person
{
    private Name name = Name.Empty;
    private Address address = Address.Empty;
    private bool canMove;

    public Name Name
    {
        set { name = value; }
        get { return name; }
    }

    public Address Address
    {
        private set { address = value; }
        get { return address; }
    }

    public bool CanMove
    {
        set { canMove = value; }
        get { return value; }
    }

    public bool MoveToNewAddress(Address newAddress)
    {
        if (!CanMove) return false;
        address = newAddress;
        return true;
    }
}

[TestFixture]
public class PersonTests
{
    private Person toTest;
    private readonly static Name NAME = new Name { First = "Charlie", Last = "Brown" };
    private readonly static Address ADDRESS =
        new Address {
            Line1 = "1600 Pennsylvania Ave NW",
            City = "Washington",
            State = "DC",
            ZipCode = "20500" };

    [SetUp]
    public void SetUp()
    {
        toTest = new Person;
    }

    [Test]
    public void NameDefaultsToEmpty()
    {
        Assert.AreEqual(Name.Empty, toTest.Name);
    }

    [Test]
    public void CanMoveDefaultsToTrue()
    {
        Assert.AreEqual(true, toTest.CanMove);
    }

    [Test]
    public void AddressDefaultsToEmpty()
    {
        Assert.AreEqual(Address.Empty, toTest.Address);
    }

    [Test]
    public void NameIsSet()
    {

        toTest.Name = NAME;
        Assert.AreEqual(NAME, toTest.Name);
    }

    [Test]
    public void CanMoveIsSet()
    {
        toTest.CanMove = false;
        Assert.AreEqual(false, toTest.CanMove);
    }

    [Test]
    public void AddressIsChanged()
    {
        Assert.IsTrue(toTest.MoveToNewAddress(ADDRESS));
        Assert.AreEqual(ADDRESS, toTest.Address);
    }

    [Test]
    public void AddressIsNotChanged()
    {
        toTest.CanMove = false;
        Assert.IsFalse(toTest.MoveToNewAddress(ADDRESS));
        Assert.AreNotEqual(ADDRESS, toTest.Address);
    }
}

In order to make the test fail first, stub the methods or properties, but do not implement any behavior. Run the tests, watch them fail, then add in behavior one line at a time until it passes. Once it passes, stop. Do not write any more code unless you write more tests (unless you're refactoring, in which case you do not add behavior).

Michael Meadows
I'll add here what Nat said bellow. Thanks Nat!TDD is all about the mindset of test first, that's you make your tests fail. Test First - Code Later.If you want to add a new feature to the class, write a test that fails because the feature has not been implemented, then implement the feature and see the test pass.
+1  A: 
  1. I believe that you shouldn't test the framework along with your own code for example if you have a auto generated property like this:

    public string Name
    {get;set;}
    

    it's not necessary to have a test method to see if it's working fine.

  2. You should not test the inner state of you class instead you should test its behavior.
  3. Sometimes (some may say always) it's better to write the test before writing the code.This way you have to understand what you want do to instead of understanding how to do it.(This approach is called test driven development)

Here's the TDD cycle:

  • Write the test and get a red signal
  • Write the code and get a green signal
  • Refactor the code and you should get a green signal
Beatles1692
@Beatles1692, I'd throw a caveat in to item #1: While it's practical to say you shouldn't test auto properties, it's potentially dangerous. It is still public, and using auto properties now doesn't preclude introducing future code (like null checking). Having set and assertion (two lines) guarantees that future developers don't accidentally change the intention of your code. You can't do test first TDD on auto properties, but generally, you should still test them.
Michael Meadows
+1 for #2 and #3 and description of TDD cycle.
Michael Meadows
@Michael, i meant one should not write some test methods just to test the framework unless it is what he intended to do.
Beatles1692
@Michael, Thanks for the vote :)
Beatles1692
+1  A: 

Perhaps by POCOs you meant DTOs, in which case the answer would be:

No you should not test your DTOs -- rather, test the services that work with them.

zvolkov
+1, Since DTOs are purely state containers, this makes perfect sense and could explain the confusion in the question. See http://stackoverflow.com/questions/725348 for POCO vs. DTO disussion
Michael Meadows