Easily Create DataTables For Unit Tests

Ideally, you have a data access layer that only returns domain objects or data transfer objects. The key is real, strongly-typed objects. One of the many reasons for this is to make unit testing easier. Unfortunately, sometimes you are stuck working with code that uses datatables. I’ve recently written a function that takes most of the pain out of creating datatables for unit testing. This function and the code that calls it takes advantage of several new c# features: lamda expressions, object initializers, list initializers, and auto-implemented properties. It also uses generics and reflection.

The first thing that stinks about creating datatables from scratch is that you have to manually define the columns which is tedious. The second thing that stinks is that you can only add rows to the datatable using an object array which means you have to count commas to keep track of which column you are populating. Or you have to do something awkward like obj[datatable.Columns[“FieldName”].Ordinal] = “somevalue”. To get around this, the first step is to define the structure of our rows by creating a simple class, EG:

public class Person
{
	public string LastName { get; set; }
	public string FirstName { get; set; }
	public DateTime DateOfBirth { get; set; }
	public decimal Salary { get; set; }
}

Now we can call the method with a very convenient syntax that capitalizes on object and list initializers:

public DataTable GetPeople()
{
	return ListToTable(new List<Person> {
		new Person {
			LastName = "Opincar",
			FirstName = "John",
			DateOfBirth = new DateTime(1901, 1, 1),
			Salary = 250000.00M
		},
		new Person {
			LastName = "Lincoln",
			FirstName = "Abe",
			DateOfBirth = new DateTime(1801, 1, 15),
			Salary = 1000.00M
		}
	});
}

If you’ve ever manually populated datatables you can really appreciate what a huge improvement this is.

Finally, we discuss the method itself. Using reflection, we can leverage the type information stored in Person to create our datatable columns in a generic method that takes a List as input and returns a datatable:

public DataTable ListToTable(List rows)
{
var dt = new DataTable();
var props = typeof(T).GetProperties();
Array.ForEach(props, p => dt.Columns.Add(p.Name, p.PropertyType));
foreach ( var r in rows )
{
object[] vals = new object[props.Length];
for (int idx = 0; idx < vals.Length; idx++) { vals[idx] = props[idx].GetValue(r, null); } dt.Rows.Add(vals); } return dt; } [/sourcecode] I hope you find this method as useful as I have.

Advertisements