Mocking generic protected methods

246 views
Skip to first unread message

esegura

unread,
Sep 18, 2011, 6:40:40 PM9/18/11
to Moq Discussions
Hi folks,

I'm trying to test my EntityFramework DbContext object. I wonder if
this is possible:


mockA.Protected().Setup<IDbSet<IEntity>>("GetSet").Returns(mockDbSet.Object).Verifiable();

where A looks like this:

public class A : DbContext{
public void Save<T>(T entity) where T : class, IEntity
{
this.GetSet<T>().Add(entity);
}

protected virtual IDbSet<T> GetSet<T>() where T : class,
IEntity
{
return this.Set<T>();
}
}

If I just do that, I get this exception:

at System.Linq.Expressions.Expression.ValidateMethodInfo(MethodInfo
method)
at System.Linq.Expressions.Expression.Call(Expression instance,
MethodInfo method, IEnumerable`1 arguments)
at Moq.Protected.ProtectedMock`1.GetMethodCall[TResult](MethodInfo
method, Object[] args)
at Moq.Protected.ProtectedMock`1.Setup[TResult](String methodName,
Object[] args)
at xyz.SaveTest() in C:\xyz.cs:line 79.

Looking at the source, it seems that we could use a new overload of
the ProtectedMock.GetMethodCall() method, one that calls a different
overload of Expression.Call(), the one with type arguments. Maybe
something like this:

private static Expression<Func<T, TResult>>
GetMethodCall<TResult>(MethodInfo method, Type[] typeArguments,
object[] args)
{
var param = Expression.Parameter(typeof(T), "mock");
return Expression.Lambda<Func<T, TResult>>(Expression.Call(param,
method, typeArguments, ToExpressionArgs(args)), param);
}

Would that work? Or there is another way to do it and I completely
missed it?
Thanks!
-e

esegura

unread,
Sep 22, 2011, 9:47:03 PM9/22/11
to Moq Discussions
-bump


Any thoughts on this? I mean, even if all I get is 'you are doing it
wrong' kind :)

Daniel Cazzulino

unread,
Oct 7, 2011, 7:00:35 AM10/7/11
to moq...@googlegroups.com
Testing a DbContext seems wrong, as you'd be testing EF itself? (it's like creating a test for system.string and trying to override stuff there ;)). 

This might be useful: http://blogs.clariusconsulting.net/kzu/how-to-design-a-unit-testable-domain-model-with-entity-framework-code-first/

/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


esegura

unread,
Oct 7, 2011, 11:15:52 PM10/7/11
to Moq Discussions
Hi Daniel,

Thanks for replying.

I'm not trying to unit test DbContext, no. I'm just trying to unit
test my code, the code in class 'A'.
But yes, after I posted that question I realized it could be
misleading. Let me try to clarify.
(I actually used that very blog post of yours to model my code)

I guess the problem was with my phrasing of the problem. Note that I
used the word "_my_" (DbContext) to refer to the class under test:
'A' (which extends from DbContext)


If you compare the code in your post:
internal class DomainContext : DbContext, IDomainContext
{
public void Save<T>(T entity) where T : IEntity
{ this.Set<T>().Add(entity); }
}

with my code above, I'm sure you will see that they look alike :):
public class A : DbContext{
public void Save<T>(T entity) where T : class, IEntity
{ this.GetSet<T>().Add(entity); }
protected virtual IDbSet<T> GetSet<T>() where T :
class,IEntity { return this.Set<T>(); }
}

So, now that that's out of the way, let me rephrase what I'm trying to
achieve: I want to mock 'GetSet()' so I can Assert that the Add()
method of the IDbSet has been called. But GetSet() is generic, thus my
question:

Is it possible to mock a protected generic method?

Thanks,
Eduardo




On Oct 7, 7:00 am, Daniel Cazzulino <dan...@cazzulino.com> wrote:
> Testing a DbContext seems wrong, as you'd be testing EF itself? (it's like
> creating a test for system.string and trying to override stuff there ;)).
>
> This might be useful:http://blogs.clariusconsulting.net/kzu/how-to-design-a-unit-testable-...

Daniel Cazzulino

unread,
Oct 7, 2011, 11:23:47 PM10/7/11
to moq...@googlegroups.com
you're testing the DbContext still. Your derived DbContext will typically have NO logic whatesoever (haven't seen a case where that would be needed).

and testing your DbContext-derived class can only make sense if it actually works against a real database, so, more of an integration test. 


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


Reply all
Reply to author
Forward
0 new messages