0

I'm having a problem creating a unit test for a method that's calling a static function and one of its parameters is a func. The problem still occurs even though I've created a wrapper class to call the static function i.e extension, as suggested in this article:

How do I use Moq to mock an extension method?

As suggested by someone, I should create an interface and a wrapper class which I did but I'm still getting an exception when it's hitting the moq setup. My setup looks as follows:

context.Setup(c => new MyExtensionWapper()
   .UpdateCollection<TestObject, int>(
   context.Object,
   databaseCollection,
   detachedCollection,
   o=>o.Id.Value));

The error occurs on the o=>o.Id.Value and the class MyExtensionWapper is the Wrapper function which implements an IExtensions with the UpdateCollection contract.

Note that my UpdateCollection is a generic function related to Entity Framework where TEntity is an EF entity object & and the TKey tends to be an Int.

public class MyExtensionWapper : IExtensions
{
    public virtual void UpdateCollection<TEntity, TKey>(IDbContext context, 
        ICollection<TEntity> databaseCollection, 
        ICollection<TEntity> detachedCollection, 
        Func<TEntity, TKey> keySelector)
        where TEntity : class
        where TKey : IEquatable<TKey>
    {
        context.UpdateCollection(databaseCollection, 
        detachedCollection, keySelector);
    }
}

When it hits the moq context.Setup(..., I get the following error:

System.NotSupportedException: 'Unsupported expression: o => o.Id.Value'

Can you help?

Thanks.

UPDATE-1

This is my original call where I tried to call a static method (extension) directly from within the mock setup:

context.Setup(c => c.UpdateCollection<TestObject, int>(
databaseCollection,
detachedCollection,
o=>o.Id.Value));

and my mock is created as follows:

context = CreateMock<IDbContext>(MockBehavior.Loose);

But when called I get the following error:

System.NotSupportedException: 'Invalid setup on an extension method:....

Update 2

As suggested by @Johnny, I should mock the interface, so I tried the following but I'm getting the same error:

Mock<IExtensions> dbExtension;

// Note: Results are the same whether I create the mock with a loose
// behaviour or not.
dbExtension = CreateMock<IExtensions>(MockBehavior.Loose);

dbExtension.Setup(c => new MyExtensionWapper()
    .UpdateCollection<TestObject, int>(
    context.Object,
    databaseCollection,
    detachedCollection,
    o=>o.Id.Value,

Also rather than calling the wrapper class, I tried to call the UpdateCollection method directly from the mock since it is defined in the interface i.e. c=>c.UpdateCollection(databaseCollection, ...) but to no avail.

Thierry
  • 6,142
  • 13
  • 66
  • 117
  • Can you at least provide feedback if you're going to down mark the question, otherwise it totally pointless! – Thierry May 02 '19 at 07:21
  • What are you trying to mock? Which method? Could you provide signature of that method. Your setup is weird... p.s. I didn't downvote – Johnny May 02 '19 at 07:22
  • @Johnny I'm trying to mock UpdateCollection which is a static collection but cannot be mocked directly so based on the provided article, one of the suggestion was to create an interface, a non static class and within that class, call the extension method. And thanks :) – Thierry May 02 '19 at 07:24
  • 1
    But then you want to mock `IExtensions`? – Johnny May 02 '19 at 07:25
  • 1
    Good that you found the solution. I think that is the way to go. – Johnny May 02 '19 at 08:09

1 Answers1

1

I eventually got it to work using the suggested method from @Johnny which was to mock to interface but I had to make a slight change to my mock:

dbExtension.Setup(c => c.UpdateCollection<TestObject, int>(
    context.Object,
    databaseCollection,
    detachedCollection,
    It.IsAny<Func<TestObject, int>>());

Instead of passing

o=>o.Id.Value

I'm not passing

It.IsAny<Func<TestObject, int>>()

Note that try to pass the It.IsAny<Func<TestObject, int>>() in my original code which called the wrapper class did not work and throws the following exception:

System.InvalidOperationException: 'No coercion operator is defined 
between types 'Extensions.MyExtensionWapper' and 'Moq.Mock'.'
Thierry
  • 6,142
  • 13
  • 66
  • 117