Verify all properties copied

42 views
Skip to first unread message

OAB

unread,
Sep 9, 2009, 9:33:23 AM9/9/09
to Moq Discussions
I have an interface with a CopyFrom() method that copies all
properties from another object. I have a test that performs several
VerifyGet() calls to ensure that each property was retrieved from the
passed object, e.g.:

IThing target = new Thing();
IThing source = new Mock<IThing>();

target.CopyFrom(source.Object);
source.VerifyGet(t => t.Foo);
source.VerifyGet(t => t.Bar);

I'd like a way to iterate over the properties of IThing though and
verify that each was copied automatically so the test will fail if
someone adds a property but forgets to copy it. Is there a way to do
this via Moq? I tried;

foreach (var prop in typeof(IThing).GetProperties())
{
source.VerifyGet(t => prop.Invoke(c, null));
}

but it didn't work since the lambda did not represent a property
accessor.

OAB

unread,
Sep 9, 2009, 4:07:50 PM9/9/09
to Moq Discussions
FYI, there is a typo in my second example. It should be:
source.VerifyGet(t => prop.Invoke(t, null));

alex2k8

unread,
Sep 9, 2009, 6:24:46 PM9/9/09
to Moq Discussions
I am afraid you will not be able to do this (but not sure). As a
possible workaround you can generate required code. E.g.

static void GenerateVerifyGet<T>(string entity)
{
foreach (var prop in typeof(T).GetProperties())
{
Console.WriteLine("{0}.VerifyGet(t => t.{1});", entity,
prop.Name);
}
}

static void Main(string[] args)
{
GenerateVerifyGet<IThing>("source");
}


Or you can make a helper method:

static void VerifyGet<T, TProperty>(Mock<T> mock, params
Expression<Func<T, TProperty>>[] actions) where T : class
{
foreach(var action in actions)
mock.VerifyGet(action);
}

VerifyGet(source, t => t.Foo, t => t.Bar);


- Alex

Andy McMullan

unread,
Sep 9, 2009, 6:50:21 PM9/9/09
to moq...@googlegroups.com
> I'd like a way to iterate over the properties of IThing though and
> verify that each was copied automatically so the test will fail if
> someone adds a property but forgets to copy it.  Is there a way to do
> this via Moq?

Perhaps there's an easier way, but you could do it by building a
LambdaExpression at runtime for each property, like this:

static void VerifyAllPropertyGets<T>(Mock<T> mock) where T : class
{
MethodInfo verifyGetMethod = GetVerifyGetMethod(mock);

foreach (var prop in typeof(T).GetProperties())
{

ParameterExpression p1 = Expression.Parameter(typeof(T), "p");
MemberExpression body = LambdaExpression.Property(p1, prop);
ParameterExpression p2 =
LambdaExpression.Parameter(typeof(T), "p");
LambdaExpression expr = LambdaExpression.Lambda(body, p2);

var closedVerifyGetMethod =
verifyGetMethod.MakeGenericMethod(prop.PropertyType);
closedVerifyGetMethod.Invoke(mock, new object[] { expr });
}
}

static MethodInfo GetVerifyGetMethod(Mock mock)
{
MethodInfo verifyGetMethod = null;
foreach (MethodInfo mi in
typeof(Mock<IThing>).GetMethods(BindingFlags.Public |
BindingFlags.Instance))
{
if (mi.Name == "VerifyGet" && mi.GetParameters().Length == 1)
{
verifyGetMethod = mi;
break;
}
}
return verifyGetMethod;
}

Then you'd use it like this:

var mock = new Mock<IThing>();

...

VerifyAllPropertyGets(mock);

Reply all
Reply to author
Forward
0 new messages