Created
December 22, 2011 09:27
-
-
Save anonymous/1509663 to your computer and use it in GitHub Desktop.
TestCollectionHelper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ReflectionHelper | |
{ | |
public static MemberExpression GetMemberExpressionGeneric<TModel, T>(Expression<Func<TModel, T>> expression) | |
{ | |
return GetMemberExpression(expression, true); | |
} | |
public static MemberExpression GetMemberExpressionGeneric<TModel, T>(Expression<Func<TModel, T>> expression, bool enforceCheck) | |
{ | |
return GetMemberExpression(expression, enforceCheck); | |
} | |
public static MemberExpression GetMemberExpression(LambdaExpression expression, bool enforceCheck) | |
{ | |
MemberExpression memberExpression = null; | |
if (expression.Body.NodeType == ExpressionType.Convert) | |
{ | |
var body = (UnaryExpression)expression.Body; | |
memberExpression = body.Operand as MemberExpression; | |
} | |
else if (expression.Body.NodeType == ExpressionType.MemberAccess) | |
{ | |
memberExpression = expression.Body as MemberExpression; | |
} | |
if (enforceCheck && memberExpression == null) | |
{ | |
throw new ArgumentException(@"Not a member access", "expression"); | |
} | |
return memberExpression; | |
} | |
public static string GetPropertyNameFrom<T>(Expression<Func<T, object>> property) | |
{ | |
var member = GetMemberExpressionGeneric(property); | |
return member.Member.Name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CollectionTestHelper<T> | |
{ | |
private IEnumerable<T> _list; | |
private Dictionary<Expression<Func<T, object>>, object> _missMatches; | |
private IEnumerable<T> _unfiltered; | |
private Dictionary<Expression<Func<T, object>>, object> _filters; | |
public CollectionTestHelper(IEnumerable<T> list) | |
{ | |
_list = list; | |
_unfiltered = list; | |
_missMatches = new Dictionary<Expression<Func<T, object>>, object>(); | |
_filters = new Dictionary<Expression<Func<T, object>>, object>(); | |
} | |
public CollectionTestHelper<T> And<T2>(Expression<Func<T, T2>> filter, T2 value) | |
{ | |
var untypedFilter = AddBox(filter); | |
_filters.Add(untypedFilter, value); | |
var filterFunc = filter.Compile(); | |
_list = _list.Where(x => Equals(filterFunc(x),value)).ToList(); | |
if (_list.Count() == 0) | |
{ | |
_list = _unfiltered; | |
_missMatches.Add(untypedFilter, value); | |
} | |
_unfiltered = _list; | |
return this; | |
} | |
public T Single() | |
{ | |
var typeName = typeof (T).Name; | |
if (_missMatches.Count > 0) | |
{ | |
var message = new StringBuilder(); | |
message.AppendFormat("{0} not found, mismatch on ", typeName); | |
foreach (var key in _missMatches.Keys) | |
{ | |
message.AppendFormat("{0}: {1}, ", ReflectionHelper.GetPropertyNameFrom(key), _missMatches[key]); | |
} | |
message.AppendFormat("\nFound with:\n"); | |
foreach (var item in _list) | |
{ | |
message.Append("\t"); | |
foreach (var key in _missMatches.Keys) | |
{ | |
message.AppendFormat("{0} = {1}, ", ReflectionHelper.GetPropertyNameFrom(key), key.Compile()(item)); | |
} | |
message.Append("\n"); | |
} | |
Assert.Fail(message.ToString()); | |
} | |
if (_list.Count() > 1) | |
{ | |
MoreThanOneMatchFail(typeName); | |
} | |
return _list.Single(); | |
} | |
private void MoreThanOneMatchFail(string typeName) | |
{ | |
var filters = new StringBuilder(); | |
foreach (var propertyExpression in _filters.Keys) | |
{ | |
var propertyName = ReflectionHelper.GetPropertyNameFrom(propertyExpression); | |
var value = _filters[propertyExpression]; | |
filters.AppendFormat("{0}: {1}, ", propertyName, value); | |
} | |
Assert.Fail("More than one {0} was found for defined filters {1}", typeName, filters); | |
} | |
private Expression<Func<TInput, object>> AddBox<TInput, TOutput>(Expression<Func<TInput, TOutput>> expression) | |
{ | |
// Add the boxing operation, but get a weakly typed expression | |
Expression converted = Expression.Convert(expression.Body, typeof(object)); | |
// Use Expression.Lambda to get back to strong typing | |
return Expression.Lambda<Func<TInput, object>>(converted, expression.Parameters); | |
} | |
} | |
public static class CollectionTestExtensions | |
{ | |
public static CollectionTestHelper<T> AssertContains<T, T2>(this IEnumerable<T> list, Expression<Func<T, T2>> filterProperty, T2 value) | |
{ | |
return new CollectionTestHelper<T>(list).And(filterProperty, value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment