RSS
 

Posts Tagged ‘Reflection’

How to use PHP’s ReflectionClass to test private methods and properties with PHPUnit

20 Jan

The other day I stumbled across PHP’s ReflectionClass that is available in version 5.3.2 or newer. It is a fantastic tool that allows you to grab information about a class and, in turn, any of its runtime objects. So, when you couple it with with PHPUnit you can easily use it to test private and protected methods and functions of any class.

Up until now, I have always found this to be a predicament in any programming language. You have a lovely class that follows all the rules of object oreiented programming, including encapsualtion and information hiding, that only exposes a small number of methods to the public. In many cases, to keep your code DRY, these public methods rely on private methods to perform task that is very specific to the class and is of no use in the public domain.

So, how do you individually test these private methods of your class without making them public? Well as you may have guessed… PHP’s ReflectionClass is one way of doing so!

The class below is good example, it has the public method validateData that relies on functionality of the constructor, where the incoming data is sorted, and the checkValue method, that ensures that the is a number between 5 and 10.

class Foo {

	private $data = array();

	/**
	 * Creates a new Foo object by taking an array of items
	 * and sorting it before setting the data property
	 * @param  $data
	 */
	function __construct($data) {
		sort($data);
		$this->data = $data;
	}

	/**
	 * Checks whether a value is between 5 and 10
	 * @param  $value
	 * @return bool
	 */
	private function checkValue($value) {
		if ($value && $value > 5 && $value < 10) {
			return true;
		}
		return false;
	}

	/**
	 * Validates the data of this class's data to ensure that all
	 * its values are sorted and between 5 and 10
	 * @return bool
	 */
	public function validateData() {
		$is_valid = true;
		$prev_value = 0;
		foreach ($this->data as $value) {
			if (!$this->checkValue($value) || $prev_value > $value) {
				$is_valid = false;
				break;
			}
			$prev_value = $value;
		}
		return $is_valid;
	}
}

Finally the PHPUnit class below is a comprehensive set of tests for the above class, it uses the ReflectionClass in each of our tests:

  • To verify that our constructor is correctly sorting the incoming array by extracting the private class property ‘data’ and checking that it is, in fact, sorted.
  • To test the private checkValue method to make sure that it conforms to our rules
  • Finally, to test the validateData method with an invalid (not sorted) array to verify it correctly returns false
class DataTest extends PHPUnit_Framework_TestCase {

	/**
	 * Foo::$data is private so lets php reflection
	 * class to test it
	 * @return void
	 */
	public function testConstructor() {
		//First we need to create a ReflectionClass object
		//passing in the class name as a variable
		$reflection_class = new ReflectionClass("Foo");

		//Then we need to get the property we wish to test
		//and make it accessible
		$property = $reflection_class->getProperty('data');
		$property->setAccessible(true);

		//We need to create an empty object to pass to
		//ReflectionProperty's getValue method
		$foo = new Foo(array(7, 6, 8));

		$this->assertEquals(array(6, 7, 8), $property->getValue($foo));
	}

	/**
	 * Foo::checkValue is private so lets php reflection
	 * class to test it
	 * @return void
	 */
	public function testCheckValue()
    {
		$reflection_class = new ReflectionClass("Foo");

		//Then we need to get the method we wish to test and
		//make it accessible
		$method = $reflection_class->getMethod("checkValue");
		$method->setAccessible(true);

		//We need to create an empty object to pass to
		//ReflectionMethod invoke method followed by our
		//test parameters
		$foo = new Foo(null);

		//Boundary test - False expected
		$this->assertFalse($method->invoke($foo, 5));

		//Good data - True Expected
		$this->assertTrue($method->invoke($foo, 7));
    }

	/**
	 * validateData relies on checkValue and the constructor.
	 * So now that, from the tests above we know that these two
	 * work as expected we can test it!
	 * @return void
	 */
    public function testValidateData()
    {
		$foo = new Foo(array(6, 7, 8 ,9));
		$this->assertTrue($foo->validateData());

		$foo = new Foo(array(10));
		$this->assertFalse($foo->validateData());

		//We may also want to test to confirm our rule that
		//the array must be sorted here.

		$reflection_class = new ReflectionClass("Foo");

		//Then we need to get the property we wish to modify,
		//set it to accessible and then override its value
		//with an invalid one
		$property = $reflection_class->getProperty('data');
		$property->setAccessible(true);
		$property->setValue($foo, array(7, 9, 8));

		$this->assertFalse($foo->validateData());
    }
}

Now because each individual method is tested you can easily pinpoint any errors that may be introduced as the code evolves. Obviously this is overkill for a simple class like this, however, you may have more complicated private methods that provide some crucial functionality to a public method that should be individially tested.

 
3 Comments

Posted in PHP, Testing

 

ASP.NET MVC – A Declarative Model Validation Technique

18 Sep

I have been doing a lot of work lately with ASP.NET MVC and found that many of the MVC examples are set up where the server that the web application runs has direct access to a database and use LINQ to SQL style validation. See Nerd Dinner example to see how the Microsoft guys validate.

My application cannot use the Nerd Dinner example because my front end IIS server does not have direct access to a database (Or in my case CICS mainframe!). So I needed a simple declarative way of validating my data before I sent it off to a web service to be inserted into the mainframe.

So, using attributes, reflection and a little help from a colleague of mine, I came up with this solution. The main algorithm in the solution is an extension method that attaches itself to the FormCollection class used by MVC. The method iterates through each method attribute attached to the properties of a given class. Inside each attribute is a validation technique that is applied to the data stored in the FormCollection, if the validation fails a model error is added to the model state.

public static void Validate(this FormCollection fc, Type t, ModelStateDictionary msd)
{
    foreach (PropertyInfo pi in t.GetProperties())
    {
        foreach (ValidatorAttribute attr in pi.GetCustomAttributes(typeof (ValidatorAttribute), true))
        {
            msd.SetModelValue(attr.Name, fc.GetValue(attr.Name));
            //ignore attributes that are not in the value list
            bool attrInValueList = (from key in fc.Keys.Cast<string>()
                                    where key.Equals(attr.Name)
                                    select key).Count() > 0;
            if (attrInValueList && !attr.Validate(fc))
                msd.AddModelError(attr.Name, attr.ErrorMessage);
        }
    }
}

As mentoned, the validation algorithm uses attributes attached to the properties of a model. The validation attributes are simple static classes that are initialised with the name of the property, an error message to display and any extra parameters that are necessary. Below is an example of regular expression and date validation attributes.

public abstract class ValidatorAttribute : Attribute
{
    protected ValidatorAttribute(string name, string errorMessage)
    {
        Name = name;
        ErrorMessage = errorMessage;
    }
    public string Name { get; set; }
    public string ErrorMessage { get; set; }
    public abstract bool Validate(FormCollection fc);
}
public class RegexValidatorAttribute : ValidatorAttribute
{
    public RegexValidatorAttribute(string name, string regex, string errorMessage)
        : base(name, errorMessage)
    {
        Regex = regex;
    }
    public string Regex { get; set; }
    public override bool Validate(FormCollection fc)
    {
        if (fc[Name] == null)
            return false;

        return new Regex(Regex).Match(fc[Name].Trim()).Success;
    }
}
public class DateValidatorAttribute : ValidatorAttribute
{
    public DateValidatorAttribute(string name, string errorMessage)
        : base(name, errorMessage) { }
    public override bool Validate(FormCollection fc)
    {
        DateTime d;
        return DateTime.TryParse(fc[Name], out d);
    }
}

Now all I did was apply these validation attributes to the properties of my model that I wanted to validate. A big note here is that the name passed as a parameter to the validation attribute must match the name of the property to be validated.

public class Client
{
    [RegexValidator("FirstName", @"^([a-zA-Z0-9\s\-]{0,12})$", "Please enter a valid first name.")]
    public string FirstName { get; set; }

    [RegexValidator("FamilyName", @"^([a-zA-Z0-9\s\-]{0,18})$", "Please enter a valid family name.")]
    public string FamilyName { get; set; }

    [DateValidator("DateOfBirth", "Please enter a valid date of birth.")]
    public string DateOfBirth { get; set; }
}

Finally, to validate your form collection all you need to do is the following. Again the keys in the form collection must match the properties of the model that is being validated.

collection.Validate(typeof(Client), ViewData.ModelState);
if (ViewData.ModelState.IsValid)
    UpdateModel(client, collection.ToValueProvider());

That’s it! Now I can clearly see in one location, the model, what the validation requirements of each property are and easily adjust them if need be. The same validation algorithm and validation attributes can be used for any model!

 
 

C# string to object model using method attributes, reflection, anonymous types and LINQ.

19 May

I came across a problem the other day where I needed to create a solution that accessed an old school string based transactional interface. The problem was a relatively simple one:

  1. Convert an object model into a string in order to be sent
  2. Receive a string and build an object model

The solution had to be robust because the transactional interface was very nit picky and the strings had to be 100% formed or it will throw all sorts of errors. It also had to be extensible allowing for more transactions to be added in the future.

I’m sure there are many ways to solve this problem however I wanted to make it scalable and declarative. So, along with a few pointers from my colleague Andrew, I decided to utilise method attributes, reflection and LINQ to solve the problem.

The following code is development code to prove a concept. Use at own risk ;-)

Building a string from an object model

Firstly I had to define my data transfer class, the restrictions imposed on its properties and the  wrapper template required by the transactional interface.

In the following example my class Foo contains the property Bar which as to be a maximum of 20 characters and must conform to the Regex displayed. Foo is also to be wrapped in the input template of max size 20.

[InputTemplate("Template Bar='{Bar}' End", 20)]
public class Foo
{
    [InputStringField(20, "^[a-zA-Z0-9]+$")]
    public string Bar { get; set; }
}

Using this approach I can define as may data transfer classes that are needed by my application and declare how they are to represented to the transactional interface.

The next step was to create a string builder that will convert the a data transfer object into a string based on the restrictions defined in the attributes of its class. I did this by reflecting the attributes and applying them to the properties of the data transfer object.

private static string BuildInputString(this T obj)
{
  var attrbutes = obj.GetType()
                     .GetCustomAttributes(typeof (InputTemplateAttribute), true)
                     .Cast();
    if (attrbutes.Count() != 1)
        throw new InvalidOperationException();

    string template = attrbutes.First().Template;

    foreach (var property in
      from prop in obj.GetType().GetProperties()
      let attributes = prop.GetCustomAttributes(typeof(InputStringFieldAttribute), true)
                           .Cast()
      where attributes.Count() > 0
      select new
             {
               PropertyInfo = prop,
               Attribute = attributes.First()
             })
    {
      if (property.PropertyInfo.GetValue(obj, null) == null)
        throw new NullReferenceException()
      string value = property.PropertyInfo.GetValue(obj, null).ToString();
      string name = property.PropertyInfo.Name;
      int length = property.Attribute.Length;

      if (value.Length > length)
        throw new InvalidOperationException();

      var regex = new Regex(property.Attribute.Format);
      if (!regex.IsMatch(value))
        throw new InvalidOperationException();

      template = template.Replace("{" + name + "}", value.PadRight(length).ToUpper());
    }
    return template;
}

The method above utilises anonymous types and reflection so it can be applied to any object that’s class definition uses the attributes defined above.

The string is then constructed using a helper function.

Foo foo = new Foo { Bar = "bar " };
string someString = foo.BuildInputString();

Building an object model from a string

Now we have to go back the other way. The transaction interface returns a string that will always conform to a set standard. So the output is declared in the same way that the input class was declared. For many of my data transfer scenarios the same class was used for input and output therefore the Input and Output attributes can be added to the same class and properties.

[InputTemplate("Template Bar='{Bar}' at Date='{Bar1}' End")]
[OutputTemplate(5)]
public class Foo
{
    [InputStringField(20, "^[a-zA-Z0-9]+$")]
    [OutputStringField(5, 0)]
    public string Bar { get; set; }    

    [OutputStringField(5, 1)]
    public string Bar1 { get; set; }
}

Now, just like the string builder above, we construct our Foo object list based on the constraints imposed on the properties in its attributes. In this example, the output string will always contain a counter of length 5 and will contain two ordered properties of max 5 characters.

public static IEnumerable BuildList(this string outputString) where T : new()
{
    if (string.IsNullOrEmpty(outputString))
        throw new InvalidOperationException();

    var obj = new T();
    var classAttrs = obj.GetType()
                        .GetCustomAttributes(typeof (OutputTemplateAttribute), true)
                        .Cast();

    if (classAttrs.Count() != 1)
        throw new InvalidOperationException();

    int count = int.Parse(outputString.Substring(0, classAttrs.First().CounterLength));

    for (int i = 0; i < count; i++)
    {
        obj = new T();
        foreach (var property in
            from prop in obj.GetType().GetProperties()
                let attributes =
                    prop.GetCustomAttributes(typeof (OutputStringFieldAttribute), true)
                        .Cast()
                        .OrderBy(a => a.Ordinal)
                where attributes.Count() > 0
                select new
                        {
                            PropertyInfo = prop,
                            Attribute = attributes.First()
                        })
        {
            string value = outputString.Substring(0, property.Attribute.Length);
            outputString = outputString.Remove(0, property.Attribute.Length);
            property.PropertyInfo.SetValue(obj, value.Trim(), null);
        }
        yield return obj;
    }
}
var fooList = someString.BuildList();

Method Attributes

I don’t think there is a need to show the attributes here as they are very simple. What you see in the constructor is what is stored in the properties of the attribute.

Conclusion

The solution above is a simplified version of what I am intending to develop, however it does show the concept of what I am doing. The solution is scalable and extensible because it can add more data transfer classes for different transactions as needed.

 
No Comments

Posted in C#