Archive for the 'Unit Testing' Category

Dynamically Generate A Class From An Interface Part 3 Unit Tests

Monday, February 6th, 2012

In Part 1 and Part 2 of Dynamically Generate A Class From An Interface, we wrote code to be able to compose objects for use in Dependency Injection as part of an overall dynamic system.  We are now actually able to take any Interface definition consisting only of properties and not only turn it into source code, but compile and instantiate an object to return.

In this post, we’ll discuss unit testing the methods created previously using MSTest built into Visual Studio 2010. I hope that it’s easy to see the value in unit testing; how would it look if I simply posted the code for this series without any testing whatsoever? While I like to consider myself an expert developer, even I make mistakes occasionally while coding. Using MSTest is very simple and will automatically generate stubs for each method within your class; simply select New Test on the Test Menu and then use the Unit Test Wizard.

First let’s create an Interface to test with, it doesn’t need to be extensive. In fact, because we’ll need to hand code what we expect to have returned from Generate, we want to keep it simple. The point is to unit test as many cases as possible as quickly as possible, not spend longer writing the test then we did the code we’re testing.


public interface ITestInterface
{
string Name { get; set; }
int Value { get; set; }
string Read { get; }
}

Next we’ll test the Generate method, if you remember from Part 1 this method actually creates the source code for the class implementing the Interface. We’ll implement this test first since in order to test the object creation method we’ll need to first be able to successfully generate source code from an interface. Alternatively we could separate the code that creates the hand created source code to check against into a separate method which can be called by the Generate test for comparison against and the Create method as the input source code.



/// <summary>
///A test for Generate
///</summary>
public void GenerateTestHelper<T>()
where T : class
{
ClassCreator target = new ClassCreator();

ClassSourceCode actual = target.Generate<ITestInterface>();

//Checking the source code is a little more complicated
StringBuilder sourceCode = new StringBuilder();

sourceCode.Append("using System;");
sourceCode.Append("using OTSD.Test.Common;");

sourceCode.Append("namespace OTSD.Test.Common");
sourceCode.Append("{");

sourceCode.Append("public class TestInterface : OTSD.Test.Common.ITestInterface");
sourceCode.Append("{");
sourceCode.Append("public System.String Name { get; set; }");
sourceCode.Append("public System.Int32 Value { get; set; }");
sourceCode.Append("private System.String read;");
sourceCode.Append("public System.String Read");
sourceCode.Append("{");
sourceCode.Append("get");
sourceCode.Append("{");
sourceCode.Append(" return read;");
sourceCode.Append("}");
sourceCode.Append("}");
sourceCode.Append("private System.String write;");
sourceCode.Append("public System.String Write");
sourceCode.Append("{");
sourceCode.Append("set");
sourceCode.Append("{");
sourceCode.Append("write = value;");
sourceCode.Append("}");
sourceCode.Append("}");
sourceCode.Append("}");
sourceCode.Append("}");

ClassSourceCode expected = new ClassSourceCode("TestInterface", sourceCode.ToString().TrimEnd());

Up till here all we’ve done is hand code the source code we expect to get back for comparison purposes. Next we actually get to the test conditions. It’s fairly straightforward as we only have two properties within ClassSourceCode to ensure are set properly. We first make sure we received the desired classname "TestInterface" and then make sure that the source code also matches. In running through the test, I found that the only issue in matching the expected source code versus the actual source code turned out to be with the Carriage Return Line Feed characters. As these don’t actually impact compilation or indicate a problem with the results, I’ve chosen to take the quick and dirty route of removing "\r\n" from the actual source code for the assert.



Assert.AreEqual(expected.ClassName, actual.ClassName);
Assert.AreEqual(expected.SourceCode, actual.SourceCode.Replace("\r\n",""));
}

[TestMethod()]
public void GenerateTest()
{
GenerateTestHelper<GenericParameterHelper>();
}

Next, we’ll populate the tests for Create. As mentioned previously, you can either call the Generate method which we tested individually from within this test or alternatively, you can separate out the code that hand creates the expected source code for the interface into a separate method which can be called in both tests.

The interesting part of this test is that we have no real way to check to make sure that the object created is correct. Instead we settle for making sure that the object has successfully implemented the passed in Interface. For all intents and purposes this should do the same thing as it tells us that the source code compiled and we were able to instantiate an object which "is" the Interface. This guarantees that the object returned can be used anywhere that an Interface of T is expected, but does not ensure that the object doesn’t have extra "junk". In other words, we rely on our test of the Generate method and the check against hand created source code to ensure that the source code going in has only what we expect. The fact that these two unit tests pass provide us with reasonable certainty that the object returned from Create has only the expected properties.


/// <summary>
///A test for Create
///</summary>
public void CreateTestHelper<T>()
{
ClassCreator target = new ClassCreator();
ClassSourceCode classSourceCode = target.Generate<ITestInterface>();
T actual;
actual = target.Create<T>(classSourceCode);
Assert.IsTrue(actual is T);
}

[TestMethod()]
public void CreateTest()
{
CreateTestHelper<ITestInterface>();
}

Well we now have the ability to take any Interface with only properties and turn it into an instantiated object that we can work with, but it doesn’t really do anything. It would be far more interesting if the object were able to populate itself from a database when provided only with the key or even return a collection of populated objects from a database based on criteria.

This actually isn’t that difficult. While we could simply modify the source code we create to include Create, Read, Update and Delete (CRUD) functionality, it would be far more interesting to create a base class that has this capability using reflection to link the properties and database operations. Then the only change to the generated source code for the class is to inherit off of this base class. This sounds like a fun challenge which we’ll undertake in the coming weeks. Check back often for an article on a dynamic CRUD base class.