Permalink
Browse files

Objects with collections as properties can now be compared using the …

…ShouldBeLike() extension method.
  • Loading branch information...
1 parent 1009584 commit e56366edf9bd5e69b6c354502ecab59313f5982e @mdwhatcott mdwhatcott committed with agross Dec 27, 2012
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace Machine.Specifications.Specs
{
@@ -111,7 +112,7 @@ public class with_incorrect_length
Because of = () => { Exception = Catch.Exception(() => _array.ShouldBeLike(new[] {"value1"})); };
It should_contain_message = () => Exception.Message.ShouldEqual(@""""":
- Expected: Array length of 1
+ Expected: Sequence length of 1
But was: 2");
It should_throw = () => Exception.ShouldBeOfType<SpecificationException>();
@@ -184,42 +185,207 @@ public class with_missing_value
[Subject(typeof(ShouldExtensionMethods))]
public class when_asserting_that_two_objects_of_the_same_concrete_type_are_like_each_other
{
+ static Exception Exception;
+ static Dummy Obj1;
+ static Dummy Obj2;
+
+ Establish context = () => { Obj1 = new Dummy {Prop1 = "test"}; };
+
+ class Dummy
+ {
+ public string Prop1 { get; set; }
+ }
+
+ public class and_the_objects_are_similar
+ {
+ Establish context = () => { Obj2 = new Dummy {Prop1 = "test"}; };
+
+ Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
+
+ It should_not_throw = () => Exception.ShouldBeNull();
+ }
+
+ public class and_the_objects_are_different
+ {
+ Establish context = () => { Obj2 = new Dummy {Prop1 = "different"}; };
+
+ Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
+
+ It should_throw = () => Exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => Exception.Message.ShouldEqual(@"""Prop1"":
+ Expected string length 9 but was 4. Strings differ at index 0.
+ Expected: ""different""
+ But was: ""test""
+ -----------^");
+ }
+
+ public class and_the_objects_are_different_and_have_null_values
+ {
+ Establish context = () => { Obj2 = new Dummy {Prop1 = null}; };
+
+ Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
+
+ It should_throw_a_specification_exception = () => Exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => Exception.Message.ShouldEqual(@"""Prop1"":
+ Expected: [null]
+ But was: ""test""");
+ }
+ }
+
+ [Subject(typeof(ShouldExtensionMethods))]
+ public class when_asserting_that_two_objects_containing_arrays_as_properties_are_like_each_other
+ {
static Exception Exception;
static Dummy Obj1;
static Dummy Obj2;
-
- Establish context = () => { Obj1 = new Dummy {Prop1 = "test"}; };
-
+
class Dummy
{
- public string Prop1 { get; set; }
+ public int[] Prop1 { get; set; }
}
+ Establish context = () => { Obj1 = new Dummy { Prop1 = new[] {1, 1, 1} }; };
+
public class and_the_objects_are_similar
{
- Establish context = () => { Obj2 = new Dummy {Prop1 = "test"}; };
-
+ Establish context = () => { Obj2 = new Dummy { Prop1 = new[] {1, 1, 1} }; };
+
Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
-
+
It should_not_throw = () => Exception.ShouldBeNull();
}
-
+
public class and_the_objects_are_different
{
- Establish context = () => { Obj2 = new Dummy {Prop1 = "different"}; };
-
+ Establish context = () => { Obj2 = new Dummy { Prop1 = new[] {2, 2, 2} }; };
+
Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
-
+
It should_throw = () => Exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => Exception.Message.ShouldEqual(@"""Prop1[0]"":
+ Expected: [2]
+ But was: [1]
+
+""Prop1[1]"":
+ Expected: [2]
+ But was: [1]
+
+""Prop1[2]"":
+ Expected: [2]
+ But was: [1]");
}
public class and_the_objects_are_different_and_have_null_values
{
- Establish context = () => { Obj2 = new Dummy {Prop1 = null}; };
+ Establish context = () => { Obj2 = new Dummy { Prop1 = null }; };
+
+ Because of = () =>
+ {
+ Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2));
+ };
+
+ It should_throw_a_specification_exception = () => Exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => Exception.Message.ShouldEqual(@"""Prop1"":
+ Expected: [null]
+ But was: System.Int32[]:
+{
+ [1],
+ [1],
+ [1]
+}");
+ }
+ }
+
+ [Subject(typeof(ShouldExtensionMethods))]
+ public class when_asserting_that_two_objects_containing_collections_as_properties_are_like_each_other
+ {
+ static ListDummy first;
+ static ListDummy second;
+ static Exception exception;
+
+ class ListDummy
+ {
+ public List<string> Prop1 { get; set; }
+ public HashSet<int> Prop2 { get; set; }
+ public IEnumerable<char> Prop3 { get; set; }
+ }
- Because of = () => { Exception = Catch.Exception(() => Obj1.ShouldBeLike(Obj2)); };
+ Establish context = () =>
+ first = new ListDummy
+ {
+ Prop1 = new List<string> {"hello", "world"},
+ Prop2 = new HashSet<int> {1, 2, 3},
+ Prop3 = new LinkedList<char>(new[] {'a', 'b', 'c'})
+ };
- It should_throw_a_specification_exception = () => Exception.ShouldBeOfType<SpecificationException>();
+ public class and_the_objects_are_similar
+ {
+ Establish context = () =>
+ second = new ListDummy
+ {
+ Prop1 = new List<string> {"hello", "world"},
+ Prop2 = new HashSet<int> {1, 2, 3},
+ Prop3 = new LinkedList<char>(new[] {'a', 'b', 'c'})
+ };
+
+ Because of = () => exception = Catch.Exception(() => first.ShouldBeLike(second));
+
+ It should_not_throw = () => exception.ShouldBeNull();
+ }
+
+ public class and_the_objects_differ
+ {
+ Establish context = () =>
+ second = new ListDummy
+ {
+ Prop1 = new List<string> { "hello", "world" },
+ Prop2 = new HashSet<int> { 3, 2, 1 },
+ Prop3 = new LinkedList<char>(new[] { 'a', 'b', 'c' })
+ };
+
+ Because of = () => exception = Catch.Exception(() => first.ShouldBeLike(second));
+
+ It should_throw = () => exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => exception.Message.ShouldEqual(@"""Prop2[0]"":
+ Expected: [3]
+ But was: [1]
+
+""Prop2[2]"":
+ Expected: [1]
+ But was: [3]");
+ }
+
+ public class and_the_objects_differ_and_have_null_values
+ {
+ Establish context = () =>
+ {
+ first.Prop2 = null;
+
+ second = new ListDummy
+ {
+ Prop1 = new List<string> {"hello", "world"},
+ Prop2 = null,
+ Prop3 = null
+ };
+ };
+
+ Because of = () => exception = Catch.Exception(() => first.ShouldBeLike(second));
+
+ It should_throw = () => exception.ShouldBeOfType<SpecificationException>();
+
+ It should_contain_message = () => exception.Message.ShouldEqual(@"""Prop3"":
+ Expected: [null]
+ But was: System.Collections.Generic.LinkedList`1[System.Char]:
+{
+ [a],
+ [b],
+ [c]
+}");
}
}
}
@@ -1,4 +1,5 @@
-using System.Linq;
+using System.Collections.Generic;
+using System.Linq;
using Machine.Specifications.Utility;
@@ -89,7 +90,7 @@ public class with_property_and_field
}
[Subject(typeof(ObjectGraphHelper))]
- public class when_getting_an_array_graph
+ public class when_getting_a_sequence_graph_with_an_array
{
static object _array;
static ObjectGraphHelper.INode _result;
@@ -100,17 +101,43 @@ public class with_no_values
{
Establish ctx = () => _array = new string[] {};
- It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.ArrayNode>();
- It should_be_empty = () => ((ObjectGraphHelper.ArrayNode) _result).ValueGetters.ShouldBeEmpty();
+ It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.SequenceNode>();
+ It should_be_empty = () => ((ObjectGraphHelper.SequenceNode) _result).ValueGetters.ShouldBeEmpty();
}
public class with_values
{
Establish ctx = () => _array = new[] {"value1", "value2"};
- It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.ArrayNode>();
- It should_contain_value1 = () => ((ObjectGraphHelper.ArrayNode) _result).ValueGetters.ElementAt(0)().ShouldEqual("value1");
- It should_contain_value2 = () => ((ObjectGraphHelper.ArrayNode) _result).ValueGetters.ElementAt(1)().ShouldEqual("value2");
+ It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.SequenceNode>();
+ It should_contain_value1 = () => ((ObjectGraphHelper.SequenceNode) _result).ValueGetters.ElementAt(0)().ShouldEqual("value1");
+ It should_contain_value2 = () => ((ObjectGraphHelper.SequenceNode) _result).ValueGetters.ElementAt(1)().ShouldEqual("value2");
+ }
+ }
+
+ [Subject(typeof(ObjectGraphHelper))]
+ public class when_getting_a_sequence_graph_with_an_IEnumerable
+ {
+ static IEnumerable<string> _sequence;
+ static ObjectGraphHelper.INode _result;
+
+ Because of = () => _result = ObjectGraphHelper.GetGraph(_sequence);
+
+ public class when_no_values
+ {
+ Establish ctx = () => _sequence = new List<string>();
+
+ It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.SequenceNode>();
+ It should_be_empty = () => ((ObjectGraphHelper.SequenceNode)_result).ValueGetters.ShouldBeEmpty();
+ }
+
+ public class when_values
+ {
+ Establish ctx = () => _sequence = new List<string> { "value1", "value2" };
+
+ It should_return_an_array_node = () => _result.ShouldBeOfType<ObjectGraphHelper.SequenceNode>();
+ It should_contain_value1 = () => ((ObjectGraphHelper.SequenceNode)_result).ValueGetters.ElementAt(0)().ShouldEqual("value1");
+ It should_contain_value2 = () => ((ObjectGraphHelper.SequenceNode)_result).ValueGetters.ElementAt(1)().ShouldEqual("value2");
}
}
@@ -299,7 +299,7 @@ static SpecificationException NewException(string message, params object[] param
if (parameters.Any())
{
return
- new SpecificationException(string.Format(message,
+ new SpecificationException(string.Format(message.EnsureSafeFormat(),
parameters.Select(x => x.ToUsefulString()).Cast<object>().ToArray()));
}
return new SpecificationException(message);
@@ -632,23 +632,23 @@ static IEnumerable<SpecificationException> ShouldBeLikeInternal(object obj, obje
return Enumerable.Empty<SpecificationException>();
}
- else if (nodeType == typeof(ObjectGraphHelper.ArrayNode))
+ else if (nodeType == typeof(ObjectGraphHelper.SequenceNode))
{
var actualNode = ObjectGraphHelper.GetGraph(obj);
- if (actualNode.GetType() != typeof(ObjectGraphHelper.ArrayNode))
+ if (actualNode.GetType() != typeof(ObjectGraphHelper.SequenceNode))
{
- var errorMessage = string.Format(" Expected: Array{0} But was: {1}", Environment.NewLine, obj.GetType());
+ var errorMessage = string.Format(" Expected: Array or Sequence{0} But was: {1}", Environment.NewLine, obj.GetType());
return new[] {NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName)};
}
- var expectedValues = ((ObjectGraphHelper.ArrayNode) expectedNode).ValueGetters;
- var actualValues = ((ObjectGraphHelper.ArrayNode) actualNode).ValueGetters;
+ var expectedValues = ((ObjectGraphHelper.SequenceNode) expectedNode).ValueGetters;
+ var actualValues = ((ObjectGraphHelper.SequenceNode) actualNode).ValueGetters;
var expectedCount = expectedValues.Count();
var actualCount = actualValues.Count();
if (expectedCount != actualCount)
{
- var errorMessage = string.Format(" Expected: Array length of {1}{0} But was: {2}", Environment.NewLine, expectedCount, actualCount);
+ var errorMessage = string.Format(" Expected: Sequence length of {1}{0} But was: {2}", Environment.NewLine, expectedCount, actualCount);
return new[] {NewException(string.Format("{{0}}:{0}{1}", Environment.NewLine, errorMessage), nodeName)};
}
@@ -3,11 +3,15 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
namespace Machine.Specifications.Utility.Internal
{
public static class PrettyPrintingExtensions
{
+ private const string CurlyBraceSurround = "{{{0}}}";
+ private static readonly Regex EscapeNonFormatBraces = new Regex(@"{([^\d].*?)}", RegexOptions.Compiled | RegexOptions.Singleline);
+
public static string FormatErrorMessage(object actualObject, object expectedObject)
{
if (actualObject == null || !(actualObject is string) ||
@@ -151,16 +155,16 @@ public static string EachToUsefulString<T>(this IEnumerable<T> enumerable)
{
var sb = new StringBuilder();
sb.AppendLine("{");
- sb.Append(String.Join(",\n", enumerable.Select(x => x.ToUsefulString().Tab()).Take(10).ToArray()));
+ sb.Append(String.Join(",\r\n", enumerable.Select(x => x.ToUsefulString().Tab()).Take(10).ToArray()));
if (enumerable.Count() > 10)
{
if (enumerable.Count() > 11)
{
- sb.AppendLine(String.Format(",\n ...({0} more elements)", enumerable.Count() - 10));
+ sb.AppendLine(String.Format(",\r\n ...({0} more elements)", enumerable.Count() - 10));
}
else
{
- sb.AppendLine(",\n" + enumerable.Last().ToUsefulString().Tab());
+ sb.AppendLine(",\r\n" + enumerable.Last().ToUsefulString().Tab());
}
}
else
@@ -194,7 +198,7 @@ internal static string ToUsefulString(this object obj)
{
var enumerable = ((IEnumerable) obj).Cast<object>();
- return obj.GetType() + ":\n" + enumerable.EachToUsefulString();
+ return obj.GetType() + ":\r\n" + enumerable.EachToUsefulString();
}
str = obj.ToString();
@@ -221,5 +225,10 @@ internal static string ToUsefulString(this object obj)
return string.Format("{0}:[{1}]", obj.GetType(), str);
}
+
+ internal static string EnsureSafeFormat(this string message)
+ {
+ return EscapeNonFormatBraces.Replace(message, match => string.Format(CurlyBraceSurround, match.Groups[0]));
+ }
}
}
Oops, something went wrong.

0 comments on commit e56366e

Please sign in to comment.