Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing the decorator pattern

I recently solved one of my problems using the decorator pattern. Everything works fine and everything is decoupled enough (or so I think) that I am able to unit test each validitable field separately.

My question is, if the NameValidator and AgeValidator both pass the tests for the Validate() and IsValid() (abstract) functions. Do I still need to unit test my ValidationDecorator class (not created yet)? ValidationDecorator would be reponsible for decorating my validator with each validation class.

public abstract class FieldValidator
{
    protected IMessage validateReturnType;

    public FieldValidator() { }

    public bool IsValid()
    {
        return (validateReturnType.GetType() == typeof(Success));
    }
}

public class NameValidator : FieldValidator, IValidator
{
    private string name;

    public NameValidator(string _name) { 
        name = _name;
    }

    public IMessage Validate()
    {
        if (name.Length < 5)
        {
            validateReturnType = new Error("Name error.");
        }
        else
        {
            validateReturnType = new Success("Name no errror.");
        }

        return validateReturnType;
    }
}

public class AgeValidator : FieldValidator, IValidator
{
    private int age;

    public AgeValidator(int _age)
    {
        age = _age;
    }

    public IMessage Validate()
    {
        if (age <= 18)
        {
            validateReturnType = new Error("Age error.");
        }
        else
        {
            validateReturnType = new Success("Age no errror.");
        }

        return validateReturnType;
    }
}

public interface IValidator
{
    IMessage Validate();
    bool IsValid();
}

This is my unit test.

[TestFixture]
public class ValidatorTest
{
    Type successType;
    Type errorType;

    Model m;

    [SetUp]
    public void SetUp()
    {
        successType = typeof(Success);
        errorType = typeof(Error);

        m = new Model();
        m.Name = "Mike Cameron";
        m.Age = 19;
        m.Height = 325;

        Validator v = new Validator();
        v.Validate(m);
    }

    [Test]
    public void ValidateNameTest()
    {
        IValidator im = new NameValidator(m.Name);

        IMessage returnObj = im.Validate();

        Assert.AreEqual(successType, returnObj.GetType());
    }

    [Test]
    public void IsValidNameTest()
    {
        IValidator im = new NameValidator(m.Name);

        IMessage returnObj = im.Validate();

        Assert.IsTrue(im.IsValid());
    }

    [Test]
    public void ValidateAgeTest()
    {
        IValidator im = new AgeValidator(m.Age);

        IMessage returnObj = im.Validate();

        Assert.AreEqual(successType, returnObj.GetType(), "Must be over 18");
    }

    [Test]
    public void IsValidAgeTest()
    {
        IValidator im = new AgeValidator(m.Age);

        IMessage returnObj = im.Validate();

        Assert.IsTrue(im.IsValid());
    }

Thank you.

like image 867
Mike Avatar asked Jun 11 '10 16:06

Mike


1 Answers

The rule of thumb is "test everything which could possibly break". Now, judging what can possibly break is far from trivial under real life circumstances. It takes practice and experience to get it right. And it is impossible to give general advice, especially without seeing your design and code.

So in the end, only you can reliably assess whether or not you feel confident enough that ValidationDecorator is so trivial, it can never break. If in doubt, it is better to err on the side of too many tests :-) That means you spend some extra time on a possibly unimportant task. The opposite - failing to write a needed unit test - means you may let a bug slip through your net, which is typically a bigger issue.

like image 50
Péter Török Avatar answered Sep 24 '22 13:09

Péter Török