TestCollectionHelper
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; | |
} | |
} |
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