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:
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.
Expected string length 20 but was 21. Strings differ at index 3.
Expected: "foo2 ToStringContent"
But was: "foo1 ToString Content"
--------------^
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 NullSafeIf you put this into your extensions project we can change this:
{
public static string ToStringNullSafe(this object obj)
{
return (obj != null) ? obj.ToString() : "NULL" ;
}
}
public override string ToString()to:
{
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);
}
public override string ToString()While we are at it, there is still one problem: M.GetType().Name
{
return string.Format("[ Type={0} M={1} Name={2} StatisticsTexts={3} ]",
M.GetType().Name,
M.ToStringNullSafe(),
Name.ToStringNullSafe(),
StatisticTexts.ToStringNullSafe());
}
This will also throw, if M is null.
Again, extensions to the rescue. Add the following code to the NullSafe class:
static class ObjectWasNull {}Note, that we just created the dummy class ObjectWasNull in order to communicate, that the object in question was null.
public static Type GetTypeNullSafe(this object obj)
{
return (obj != null) ? obj.GetType() : typeof(ObjectWasNull);
}
This will give us some helpfull output instead of failing totally.
Lets show another example:
Lets say we have a class:
class sutIn the test we try the following:
{
Panel uninitializedPanel;
public override string ToString()
{
return uninitializedPanel.ToString();
}
}
sut sut1 = new sut();This will give us a very ugly message like:
sut sut2 = new sut();
sut2.uninitializedPanel = new Panel();
Assert.That(sut1, Is.EqualTo(sut2));
(......)Not very nice.
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)
(......)
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: extension methods, tdd, testing
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home