Wednesday, July 1, 2009

Mocking a timer

Most of us in the testing world are probably familiar with the following problem:

We want to test, that once we call a method, it will start a timer which will then invoke another method when the interval elapsed.

A very simple test, that just deals with the System Timer itself could look like this:

var mockTimer = new System.Timers.Timer(1);

bool elapsedFired = false;
mockTimer.Elapsed += (sender, e) => elapsedFired = true;
mockTimer.Start();

Assert.That(elapsedFired);
Although we told it to fire after only 1ms, this test will fail (at least most times) because the Assert will be examined before the timer fired - all thanks to our fast technologies.
One remedy would be to make sure we wait long enough so the timer has a chance to fire by adding: System.Threading.Thread.Sleep(200);

The revised test looks like this:
var mockTimer = new System.Timers.Timer(1);

bool elapsedFired = false;
mockTimer.Elapsed += (sender, e) => elapsedFired = true;
mockTimer.Start();

System.Threading.Thread.Sleep(200);

Assert.That(elapsedFired);
It will now pass. So problem solved? Not at all, just found a questionable workaround.
This solution is bad for two reasons.
  1. The test could still fail whenever the timer thread is much slower than the one we are on.
  2. If we have a lot of tests like that, they will take a very long time, which needs to be avoided.
Today though I was faced exactly with this problem.
At first I tried to mock the timer using Moq, to at least verify, that the timer.Start() method got called. Unfortunately for unknown reasons Moq will claim, that it didn't get called at all even though I called it inside the test. So this doesn't seem to work.
Additionally, I would like to check, that the registered methods get invoked, when the Elapsed Event fires.
So I tried another route.

I created a class FireOnStartTimer that inherits from System.Timers.Timer in which I tried to trigger the Elapsed event by hand, right when the timer is started, like so:
public new void Start()
{
this.Elapsed.Invoke(this, new EventArgs() as System.Timers.ElapsedEventArgs);
}
Notice that I couldn't override the Start() method, therefore I used new void Start() instead.

The compiler didn't like that solution though and gave me this error:
The event 'System.Timers.Timer.Elapsed' can only appear on the left hand side of += or -= (CS0079)

What to do?
I decided to "new" the Elapsed Eventhandler itself as well, hoping that since then my class "owns" it, I would be allowed to do what I tried previously.
I added:
public new event System.Timers.ElapsedEventHandler Elapsed;


Bingo! Now it compiled!

I ran the previous test, without the ugly System.Threading.Thread.Sleep(200);:
var mockTimer = new FireOnStartTimer();

bool elapsedFired = false;
mockTimer.Elapsed += (sender, e) => elapsedFired = true;
mockTimer.Start();

Assert.That(elapsedFired);
And it passed still.

Mission accomplished!

Here is the complete FireOnStartTimer class:

class FireOnStartTimer : System.Timers.Timer
{
public new event System.Timers.ElapsedEventHandler Elapsed;

public FireOnStartTimer() : base() {}
public FireOnStartTimer(double interval, ISynchronizeInvoke syncObject)
: this()
{
this.SynchronizingObject = syncObject;
this.AutoReset = false;
this.Enabled = true;
this.Interval = interval;
}

public new void Start()
{
this.Elapsed.Invoke(this, new EventArgs() as System.Timers.ElapsedEventArgs);
}
}
For convenience I have added a Constructor which sets up the timer for me, this is not required though, so this would be the essence of an hour of experimentation:
class FireOnStartTimer : System.Timers.Timer
{
public new event System.Timers.ElapsedEventHandler Elapsed;

public new void Start()
{
this.Elapsed.Invoke(this, new EventArgs() as System.Timers.ElapsedEventArgs);
}
}

Tiny but of great use.

Finally I needed to create a Timer interface and an adapter for the System.Timers.Timer that implements the interface.
It is necessary to pass the timer into the system under test as ITimer in order to make use of polymorphism and in that way ensure that the Start() method of our custom timer is called during testing. If we would just pass it in as System.Timers.Timer, our Custom Start() method is never invoked, but instead the one of System.Timers.Timer. Also we want to avoid any
if (myTimer is FireOnStartTimer)
(myTimer as FireOnStartTimer).Start();
else
(myTimer as System.Timers.Timer).Start();

kind of mess.

Since both Timer classes implement the ITimer interface, we can pass in our custom Timer during testing and the Adapter for the System.Timers.Timer in the production code, without having to change the class we are testing.

Here is that interface:

public interface ITimer
{
void Start();
void Stop();
void Close();

bool AutoReset { get; set; }
bool Enabled { get; set; }
double Interval { get; set; }
ISynchronizeInvoke SynchronizingObject { get; set; }

event ElapsedEventHandler Elapsed;
}


and the adapter:
/// <summary>
/// Adapts the System.Timers.Timer class to implement the ITimer interface.
/// </summary>
public class SystemTimerAdapter : Timer, ITimer
{
public SystemTimerAdapter() : base() {}
public SystemTimerAdapter(double interval) : base(interval) {}
}


Of course other timers could also be used with above interface. All we need to do is write an adapter for them.

Labels: , , , ,

Saturday, June 27, 2009

Revised Generic class ToString() Method

After reading this great blog by Rinat Abdullin, I decided to revise my Generic ToString solution somewhat.

Here is the complete class:


/// <summary>
/// Creates a string of this format: MemberType MemberName=MemberValue
/// Usage:
/// <code>
/// string testMember = "testing";
/// Console.WriteLine(Member.State(() => testMember));
/// </code>
/// Writes ' string testMember="testing" ' to the Console.
/// </summary>
public static class Member
{
public static string State<T>(Func<T> expr)
{
var member = ExtractMemberFromLambdaExpression(expr);

Type memberType = GetTypeOfMember(member);

string contents = ExtractContentsFromLambdaExpression(expr);

return string.Format("{0} {1}={2}",memberType.Name, member.Name, contents);
}

static string ExtractContentsFromLambdaExpression<T>(Func<T> expr)
{
if (expr() == null) {
return "NULL";
}

string contents = string.Empty;
if (expr().GetType().IsArray) {
foreach (var item in (expr() as Array)) {
contents += item.ToStringNullSafe() + ", ";
}
contents = contents.Trim().TrimEnd(',');
} else {
contents = expr().ToString();
}

return contents;
}

static MemberInfo ExtractMemberFromLambdaExpression<T>(Func<T> expr)
{
// get IL code behind the delegate
var il = expr.Method.GetMethodBody().GetILAsByteArray();
// bytes 2-6 represent the member handle
var memberHandle = BitConverter.ToInt32(il, 2);
// resolve the handle
return expr.Target.GetType().Module.ResolveMember(memberHandle);
}


static Type GetTypeOfMember(MemberInfo member)
{
Type memberType;
if (member.MemberType == MemberTypes.Field) {
memberType = GetFieldType(member as FieldInfo);
}
else if (member.MemberType == MemberTypes.Property) {
memberType = GetPropertyType(member as PropertyInfo);
}
else {
memberType = typeof(object);
}
return memberType;
}

static Type GetFieldType(FieldInfo fieldInfo)
{
return fieldInfo.FieldType;
}

static Type GetPropertyType(PropertyInfo propertyInfo)
{
return propertyInfo.PropertyType;
}
}

As you can see from the supplied example in the XML documentation header, the use has become much simpler.
It is now using Lambda expressions in order to return its values.

This method uses strongly-typed reflection on the passed in lambda expression in order to obtain type and name of the field and invokes the ToStringNullSafe() method on the expression itself in order to obtain the value from the field.

In case you are wondering about the ToStringNullSafe() method - I created these in my previous blog.

Fortunately using the new Member.State() method is a lot easier than understanding the details, but I encourage you to read Rinat Abdullin's blog if you want to find out more. All I needed to know in order to implement this improved version, I found in there.

The big advantage of this new solution compared to the previous one, is, that now we don't have to implement an interface nor worry about the order of declaration of our member variables.
Additionally, they don't even have to be member variables. The new solution works for almost any object that implements a ToString() method.

As you can see from the ExtractContentsFromLambdaExpression method, if it encounters an array, it will return the contents of each value in the array.
It will not however return anything useful when it encounters a collection that is not an array, or any object, that doesn't implement a meaningful ToString() method. So think about what you pass into it.

Here a short example of how to use it to print information about a class:


public class PrintMyInfo
{
string infoString;
int counter;
double[] arrayOfValues;
List<string> lstString;
public PrintMyInfo()
{
this.infoString = "Info";
this.counter = 12;
this.arrayOfValues = new double[] { 0.3, 0.5, 23.2};
lstString = new List<string>();
lstString.Add("item1");
lstString.Add("item2");
}

public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("PrintMyInfo: ");
sb.AppendLine(Member.State(() => this.infoString));
sb.AppendLine(Member.State(() => this.arrayOfValues));
sb.AppendLine(Member.State(() => this.counter));
sb.AppendLine(Member.State(() => this.lstString.ToArray()));
return sb.ToString();
}
}

Note how we need to copy the List to an array in order to get meaningful output.


Console.WriteLine(new PrintMyInfo().ToString());
produces the following output:
PrintMyInfo:
String infoString=Info
Double[] arrayOfValues=0.3, 0.5, 23.2
Int32 counter=12
List`1 lstString=item1, item2
Should we ever need to change any variable names in our class, the refactoring tool, will adjust our ToString() method automatically, since nothing is hardcoded in a string except the class name.

Labels: , ,

Friday, June 26, 2009

More Extensions - The Generic ToString() Method for classes and structs

NOTE: The following solution has been improved a lot in this blog.

Don't you hate repetitive tasks?

I sure do.
Writing ToString() methods for classes is one of them.
We will implement the same kind of ToString() methods if we need them to give us information about the object state as is very usefull when running UnitTests or logging exceptions.

Here is a typical example:

class ControlData
{
public Point location;
public Size size;

public ControlData(Point location, Size size)
{
this.location = location;
this.size = size;
}

public override string ToString()
{
return string.Format("[ControlData: {0} location={1} size={2}]", this.location, this.size);
}
}


Granted, codegenerators will do this job for you.
But what if you want to rename some fields or the class itself.
In that case you have to generate the ToString() method all over again, since the rename refactoring will not change anything inside of strings.
In our case, were we to change 'location' to 'firstLocation' its name in here:
"[ControlData: {0} location={1} size={2}]"

will not change with it.

Turns out, that there is a way to automate a ToString() execution alltogether. So without any further ado:

public static string FieldsToString<T>(this T fieldContainer) where T : IFieldsEnumerable
{
var sb = new StringBuilder();
int fieldCount = 0;

sb.AppendFormat("[{0}:", fieldContainer.GetType().Name);

foreach (var field in fieldContainer.GetFieldEnumerator())
{
sb.AppendFormat("\n {0}\t{1}\t{2} ",
fieldContainer.GetType().GetFields()[fieldCount].FieldType.Name,
fieldContainer.GetType().GetFields()[fieldCount].Name,
field.ToString());
fieldCount++;
}

sb.Append("]");

return sb.ToString();
}

Now lets look at the previous class again, except that it now implements the IFieldsEnumerable interface:

class ControlData : IFieldsEnumerable
{
public Point location;
public Size size;

public ControlData(Point location, Size size)
{
this.location = location;
this.size = size;
}

public override string ToString()
{
return this.FieldsToString();
}

public IEnumerable<object>GetFieldEnumerator()
{
yield return location;
yield return size;
}
}

Here is that interface:

public interface IFieldsEnumerable
{
IEnumerable<object>GetFieldEnumerator();
}
Calling:
new ControlData(new Point(12, 13), new Size(21, 30)).ToString();

produces this neat output:
[ControlData:
Point location {X=12,Y=13}
Size size {Width=21, Height=30} ]

Of course we could also have called FieldsToString() directly as in:
new ControlData(new Point(12, 13), new Size(21, 30)).FieldsToString();
with the same result.
Important is that the order of the yields in the GetFieldEnumerator() method exactly matches the order in which the fields are declared int the class. Otherwise the values of the fields will not line up with their names.
This requirement is caused by the fact, that the fieldnames are obtained from the class via reflection.

Now, if we want to change any field names, we can go ahead and be sure that all necessary changes in order to produce the correct ToString() output will be done automatically as we are not dealing with hard coded strings in the this method anymore.

If we add another field xxx , we just add a yield return xxx to the GetFieldEnumrator() method and are done.

Just to be clear, add the FieldsToString() method to your extension class and include the IFieldsEnumerable interface in the same project.

Now you just need to implement this interface for the classes to which you want this extra functionality.

Labels: , ,

Thursday, June 25, 2009

Extension methods and Unit Testing

When unit testing, we soon find out, that the testing framework (like NUnit) will use the ToString() method of an object in order to show the reason why an Equality Assertion fails.
Lets take or instance:
Assert.That(foo1, Is.EqualTo(foo2));
If this test fails, NUnit will try to show you where the objects where different by using the ToString() method as such:

Expected string length 20 but was 21. Strings differ at index 3.
Expected: "foo2 ToStringContent"
But was: "foo1 ToString Content"
--------------^
The problem with that is, that if we list a lot of fields in our ToString() method, the above Action of NUnit will throw a null reference exception, if only one of these fields wasn't initilaized. This will happen more often when using Mock objects.
In that case of course, we will never know what NUnit was trying to tell us. Not very desireable.

Therfore I decided that I'd need a null safe ToString() method. Instead of throwing an exception if the object is null, it will just return a string, that tells me that it was null.

public static class NullSafe
{

public static string ToStringNullSafe(this object obj)

{
return (obj != null) ? obj.ToString() : "NULL" ;

}

}
If you put this into your extensions project we can change this:
public override string ToString()
{

string strM = (M != null) ? M.ToString() : "null";
string strName = (Name != null) ? Name.ToString() : "null";
string strStatisticTexts = (StatisticsTexts != null) ? StatisticsTexts.Contents.ToString() : "null";

return string.Format("[ Type={0} M={1} Name={2} StatisticsTexts={3} ]",
M.GetType().Name, strM, strName, strStatisticTexts);
}
to:

public override string ToString()
{
return string.Format("[ Type={0} M={1} Name={2} StatisticsTexts={3} ]",
M.GetType().Name,
M.ToStringNullSafe(),
Name.ToStringNullSafe(),
StatisticTexts.ToStringNullSafe());
}
While we are at it, there is still one problem: M.GetType().Name
This will also throw, if M is null.

Again, extensions to the rescue. Add the following code to the NullSafe class:

static class ObjectWasNull {}
public static Type GetTypeNullSafe(this object obj)
{

return (obj != null) ? obj.GetType() : typeof(ObjectWasNull);
}
Note, that we just created the dummy class ObjectWasNull in order to communicate, that the object in question was null.

This will give us some helpfull output instead of failing totally.

Lets show another example:
Lets say we have a class:

class sut
{
Panel uninitializedPanel;
public override string ToString()
{
return uninitializedPanel.ToString();
}
}

In the test we try the following:

sut sut1 = new sut();
sut sut2 = new sut();


sut2.uninitializedPanel = new Panel();


Assert.That(sut1, Is.EqualTo(sut2));
This will give us a very ugly message like:

(......)
System.NullReferenceException : Object reference not set to an instance of an object.
at ( ...) TestClass.cs:line 145
at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, String format, Object[] args)
at System.String.Format(IFormatProvider provider, String format, Object[] args)
at System.IO.TextWriter.Write(String format, Object arg0)
at NUnit.Framework.TextMessageWriter.WriteValue(Object val)
at NUnit.Framework.TextMessageWriter.WriteExpectedValue(Object expected)
at NUnit.Framework.TextMessageWriter.WriteExpectedLine(Object expected, Tolerance tolerance)
at NUnit.Framework.TextMessageWriter.DisplayDifferences(Object expected, Object actual, Tolerance tolerance)
at NUnit.Framework.Constraints.EqualConstraint.DisplayDifferences(MessageWriter writer, Object expected, Object actual, Int32 depth)
at NUnit.Framework.Constraints.EqualConstraint.WriteMessageTo(MessageWriter writer)
at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args)
at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression)
(......)
Not very nice.
Now lets change:
return uninitializedPanel.ToString();
to:
return uninitializedPanel.ToStringNullSafe();

and we get
Test Failure : ( ... )
Expected: System.Windows.Forms.Panel, BorderStyle:
System.Windows.Forms.BorderStyle.None
But was: NULL

Much nicer indeed.

Labels: , ,