Hi,
We have the following method signature:
public IEnumerable<TResult> GetGroupedBy<TKey, TResult>(Expression<Func<TEntity, bool>> whereClause,
Expression<Func<TEntity, TKey>> keySelector,
Expression<Func<TKey, IEnumerable<TEntity>, TResult>> resultSelector)
{
// SomethingHere
}
We are unable to mock if TResult is an anonymous type, even if I explicitly set it as an object (as suggestion on some Stackoverflow thread). It seems to be a limitation of the API.
Is it possible to help me with this?
Thank you,
Dave
Hi @DaveWut. Assuming that it were possible to mock anonymous types, I am not sure I understand why and how would that be useful? At the language level (i.e. excluding any reflection acrobatics), objects of an anonymous type are next to useless outside the method in which they were created, so such a mock would likely be limited by a method boundary as well.
As to why Moq 4 doesn't (and cannot) support mocking anonymous types: they are declared non-public and sealed, so there's no way to subclass them. Fields/properties are likely non-virtual, so Moq couldn't intercept them (by overriding them). Moq 4 can only mock virtual, non-sealed methods, nothing we can do to change that (at least not without a totally different technological foundation and a complete rewrite).
Moq 4.9 it seems to work with setting object.
However, if you test through some layer, you don't know the "generic type". Then you would need to register this through some sort of helper method to extract the signature.
The Anonymous type signature is not known until the application is compiled, therefor the only way to do this is through a helper method, or inject some code with a custom plugin for Fody, PostSharp or similar (that I don't think exist).
Can't really see any other way of doing this. See @stakx answer.
My full example (in LINQPad with helper method "hack" and object registration "hack"):
void Main()
{
var mock = new Mock<ITest<object>>();
//Signature registered: (object, object, object)
mock.Setup(m => m.GetGroupedBy(It.IsAny<Expression<Func<object, bool>>>(), It.IsAny<Expression<Func<object, object>>>(), It.IsAny<Expression<Func<object, IEnumerable<object>, object>>>()))
.Returns(new[] { new { SomeField = "AnonymousType" } });
//Using helper register method:
RegisterByHelperMethod(mock, new { SomeField = "AnonymousType" });
//Explicit signature: (object, string, string[])
mock.Setup(m => m.GetGroupedBy(It.IsAny<Expression<Func<object, bool>>>(), It.IsAny<Expression<Func<object, object>>>(), It.IsAny<Expression<Func<object, IEnumerable<object>, string>>>()))
.Returns(new[] { "mock" });
//... .Dump() is a LinqPad extension.
mock.Object.GetGroupedBy<object, object>(null, null, null).Dump(); //Returns: new [] { new object() }
mock.Object.GetGroupedBy<object, string>(null, null, null).Dump(); //Returns: new[] { "mock" }
var wrapper = new Wrapper();
wrapper.WithSignature(mock.Object, new { A = "AnonymousType" }).Dump(); //Not a registered signature.
wrapper.WithSignature(mock.Object, new { SomeField = "AnonymousType" }).Dump(); //Work throuh helper Register method Method.
try
{
//Expected: Unable to cast object of type '<>f__AnonymousType0`1[System.String]' to type '<>f__AnonymousType1`1[System.String]'.
//Object signature is registered, but not to this anonymous type (wrong return in this case).
wrapper.WithObject(mock.Object, new { A = "AnonymousType" }).Dump();
}
catch (InvalidCastException)
{
Console.WriteLine("Registered an other type as different object type, so cast is invalid from 'new { SomeField }' to 'new { A }'!");
}
wrapper.WithObject(mock.Object, new { SomeField = "AnonymousType" }).Dump(); //Casting is valid
}
void RegisterByHelperMethod<TAnonymous>(Mock<ITest<object>> mock, TAnonymous someHelperObjectWithUnknownType)
{
mock.Setup(m => m.GetGroupedBy<object, TAnonymous>(It.IsAny<Expression<Func<object, bool>>>(), It.IsAny<Expression<Func<object, object>>>(), It.IsAny<Expression<Func<object, IEnumerable<object>, TAnonymous>>>()))
.Returns(new[] { someHelperObjectWithUnknownType });
}
public interface ITest<TEntity>
{
IEnumerable<TResult> GetGroupedBy<TKey, TResult>(
Expression<Func<TEntity, bool>> whereClause,
Expression<Func<TEntity, TKey>> keySelector,
Expression<Func<TKey, IEnumerable<TEntity>, TResult>> resultSelector
);
}
public class Wrapper
{
public object WithSignature<TEntity, TOutput>(ITest<TEntity> entity, TOutput outputType)
{
//Signature used: (object, object, anonymous)
return entity.GetGroupedBy<object, TOutput>(null, null, null).FirstOrDefault();
}
public TOutput WithObject<TEntity, TOutput>(ITest<TEntity> entity, TOutput outputType)
{
//Signature used: (object, object, object)
return (TOutput)entity.GetGroupedBy<object, object>(null, null, null).FirstOrDefault();
}
}
Edit, here is my output:

Hi @oddbear . I tried your helper function, but without success. I've configured Moq with strict behaviour instead of loose and each time it goes through the place, an exception is thrown telling me the mock hasn't been configured for that kind of call.
Hi @stakx it seems like my only resort is to create a POCO with the returned object, then I'm able to test it. I understand at first you can have difficulties understanding the purpose of mocking a generic anonymous types, but I hope with the following explanation, you will understand. The method I'm trying to mock is a call to a database and the result is used only scoped in a private method. Since the call is done by a "parent" public method, in only a certain path this particular private method is called and I have no other controls than that mocking data and sub calls to services in order to make it go through that particular place. Data returned by the IRepository is important and a slight change can make the code respond in a lot of different manners. The anonymous object is only a more elegant way of returning a bunch of data without creating a class or returning a Tuple.
@oddbear: I am afraid I cannot piece together what you're attempting to do from your description, an actual minimal & complete code example would be helpful. Please include the error message you're getting.
Could this be a duplicate of #552?
@DaveWut in my example, it only fails for the one commented with "//Not a registered signature." when using strict (as this signature is not registered). Without a more complete code example, I can't see whats the problem.
@stakx minified example of just the helper method workaround:
void Main()
{
var mock = new Mock<ITest>(MockBehavior.Strict);
//As TAnonymous is unknown at this point, we can use the helper hack to extract it without manual reflection:
RegisterByHelperMethod/*<TAnonymous>*/(mock, new { A = "AMock" } ); //However this must have exact the same signature as you want to mock.
//Several registrations is possible:
RegisterByHelperMethod(mock, new { B = "BMock" } );
Console.WriteLine(mock.Object.MockMe(() => new { A = "A" }).A); //"AMock"
Console.WriteLine(mock.Object.MockMe(() => new { B = "B" }).B); //"BMock"
}
void RegisterByHelperMethod<TAnonymous>(Mock<ITest> mock, TAnonymous anonymous)
{
//TAnonymous is known at this point:
mock.Setup(m => m.MockMe<TAnonymous>(It.IsAny<Expression<Func<TAnonymous>>>()))
.Returns(anonymous);
}
public interface ITest
{
TResult MockMe<TResult>(Expression<Func<TResult>> func);
}
We don't need to specify the anonymous type (that is unknown) to the method, as the compiler is smart enough to figure it out for us. But it is important that the anonymous type we paste inn will have the same signature (property names), as the one we are trying to mock.
Edit:
@DaveWut, apologies, I meant to address you in my above post, not @oddbear.
it seems like my only resort is to create a POCO with the returned object, then I'm able to test it.
It is really hard to help if you don't show a minimal, runnable code example of what you're attempting to do. You're saying you're attempting to mock something, but it's not clear what you're mocking, you're just describing your actual code as "it" and "the place". I'd just have to guess.
Please post a short, runnable repro code, then I can look into this (but it might still turn out to be a duplicate of #552). Without a repro, I'll close this issue in a few days' time.
Hi @stakx, I will try to make an example as soon as possible and I'll come back here to post it.
Hi @stakx,
So let's say. We have a class named InjectableClass that implements IInjectableClass. Upon registration of the modules using Autofac, the class gets an instance of a IEfRepository
So here we are, we want to test this class:
public class InjectableClass : IInjectableClass
{
private readonly IEfRepository<ProductLocalized, IPmDbContext> _productLocalizedRepository;
public InjectableClass(IEfRepository<ProductLocalized, IPmDbContext> productLocalizedRepository)
{
_productLocalizedRepository = productLocalizedRepository;
}
public void Run()
{
var productNameAndDesc = _productLocalizedRepository.GetBySingle(localized => localized.Id == 1,
localized => new { localized.Name, localized.Description });
System.Console.WriteLine(productNameAndDesc != null ? "This is working." : "This is not working.");
}
}
The repository that gets injected let me select on the fly what entity I want to fetch from the database and on what context the data exists. An IEfRepository looks like that:
public interface IEfRepository<TEntity, TDbContext>
where TEntity : class
where TDbContext : IEfDbContext
{
TResult GetBySingle<TResult>(Expression<Func<TEntity, bool>> whereClause,
Expression<Func<TEntity, TResult>> resultExpression);
}
A IEfDbContext is simply a DbContext, abstracted the way I want using Autofac. For the purpose of the demonstration, this is not important. Let's just concentrate on the signature of the method in this interface. The interesting part, the generic TResult of GetBySingle, allows a programmer to return virtually anything from this function. I wanted to filter an EF query "to the bones". So what I mean by that is that I can return from the SELECT statement generated by EF, only the columns I want. That's where the anonymous TResult comes handy in the case. Still don't need to manually create a POCO and I still can get a structured and typed variable from the EF query.
Now the problem. The class InjectableClass is simply untestable from the current state. Here's both ways I tried to do so:
[TestClass]
public class InjectableClassTests
{
[TestMethod]
public void RunRepoTestStrictWithoutHelper()
{
using (var mock = AutoMock.GetStrict())
{
mock.Mock<IEfRepository<ProductLocalized, IPmDbContext>>().Setup(repository =>
repository.GetBySingle(It.IsAny<Expression<Func<ProductLocalized, bool>>>(),
It.IsAny<Expression<Func<ProductLocalized, object>>>()))
.Returns(new { Name = "SomeName", Description = "SomeDescription" });
var sut = mock.Create<InjectableClass>();
sut.Run();
// Will crash.
}
}
[TestMethod]
public void RunRepoTestStrictWithHelper()
{
using (var mock = AutoMock.GetStrict())
{
mock.Mock<IEfRepository<ProductLocalized, IPmDbContext>>()
.MockRepository(new {Name = "SomeName", Description = "SomeDescription"});
var sut = mock.Create<InjectableClass>();
sut.Run();
// Will crash.
}
}
}
BTW, I'm using Autofac.Extras.Moq to run my tests. AutoMock.GetStrick has the expected behavior. If I do not explicitly mock my stuff, it crashes. This is what happen in both test. Even with this helper inspired from @oddbear:
public static void MockRepository<TAnonymous>(this Mock<IEfRepository<ProductLocalized, IPmDbContext>> mock,
TAnonymous returnType)
{
mock.Setup(repository => repository.GetBySingle(It.IsAny<Expression<Func<ProductLocalized, bool>>>(),
It.IsAny<Expression<Func<ProductLocalized, TAnonymous>>>()));
}
Injected type is really what I expect from the other end:

But alas, still unsuccessful. I really hope the explanation helps you understand the problem. If you have any question, please don't hesitate. In any case, the source code of my example is still on my computer, so if you need more details, I can provide the full example.
Thank you.
@DaveWut: You are invoking a different method than the one you're setting up. You are setting up object GetBySingle<object>(...) but you are calling 'a GetBySingle<'a>(...), that's why you receive a strict mock error when the call happens. (Moq performs an exact match of the return type when matching invocation against setup.)
See also #552, of which this is a duplicate.
@DaveWut , I tested with the helper, and I think the code is set up the same way as yours _(see attachment)_, the only thing I needed to change to get it working, is the missing Return setup in the Helper method. If this is not set, it will return null and: "This is not working.", instead of: "This is working.".
Maybe using Helper Methods like this should be put in the Wiki? At least I find those quite helpful.
public static void MockRepository<TAnonymous>(this Mock<IEfRepository<ProductLocalized, IPmDbContext>> mock,
TAnonymous returnType)
{
mock.Setup(repository => repository.GetBySingle(It.IsAny<Expression<Func<ProductLocalized, bool>>>(),
It.IsAny<Expression<Func<ProductLocalized, TAnonymous>>>()))
.Returns(returnType) //<- missing in your example, will always return null
;
}
Test result:
Running 2 of 2 tests...
[SKIP] UserQuery.RunRepoTestStrictWithoutHelper: Original Without
This is working.
Finished: 2 tests in 0,442s (0 failed, 1 skipped)
Adding working Linqpad code example:
CodeExampleLinkpad.zip
@stakx this is true only for the RunRepoTestStrictWithoutHelper test.
The RunRepoTestStrictWithHelper is setup with TAnonymous _(as the compiler is smart enough to figure this out by itself)_ by using the MockRepository extension method.
However, the setup is missing setup of the Return(TAnonymous). After I changed this, it worked as expected.
What do you think about putting something about this trick in the documentation?
It's quite helpful to be able to mock anonymous types this way. And for now, I don't see any other way of doing it.
@oddbear:
What do you think about putting something about this trick in the documentation?
Sure, feel free to add something e.g. in the Wiki. I'd recommend to place this, not in the Quickstart, but as a separate FAQ of some sort. If you, or anyone else, could write up an article about anonymous types that's reasonably general and with a very simple example, that'd be great!
Regarding the other test, it's true I sort of overlooked it. I'm currently away from my dev machine but will take another look when I get the chance.
For now, how do you all think we should proceed? Are you OK with just adding documentation for this kind of problem, or is there anything else we should do?
@stakx Since the examples worked, I would think this is not a issue at all.
Don't see how it can be improved either in a good way, as the limitations is mostly in C# and not in Moq.
Since there is a workaround (that I have used in many tests already), I would think is better to document that one, than trying to create a solution.
@DaveWut, what do you think?
@stakx added some examples under the FAQ section: https://github.com/moq/moq4/wiki/FAQ
@oddbear: Very nice! Thanks for putting up this FAQ!
@DaveWut, @oddbear - If you think there's anything left to do here, please speak up. Otherwise I'll close this issue in about 3-4 days' time.
I indeed made an error in the example code I've given. Thanks for pointing it out @oddbear . Documentation is cool, but still sounds more like a hack than a way Moq should work. I saw #343 and liked the idea of an It.IsAnyType. Maybe this is something that could be implemented in the library eventually?
@DaveWut - Agreed. Let me close this present issue then, and reopen #343 instead. I'll try to find out how much work would be needed to bring it up-to-date and include it in a future release.
Most helpful comment
@oddbear: Very nice! Thanks for putting up this FAQ!