从使用func作为参数的最小订量中调用扩展方法时引发异常

时间:2019-05-01 22:56:13

标签: unit-testing mocking moq extension-methods

我在为调用静态函数的方法创建单元测试时遇到问题,其参数之一是func。即使我已经创建了一个包装器类来调用静态函数(即扩展名),也仍然会出现该问题,如本文中所建议的:

How do I use Moq to mock an extension method?

正如某人建议的那样,我应该创建一个接口和一个包装类,但我在达到最低定额设置时仍然遇到异常。我的设置如下:

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

该错误发生在o=>o.Id.Value上,类MyExtensionWapper是Wrapper函数,该函数使用UpdateCollection合同实现IExtensions。

请注意,我的UpdateCollection是与Entity Framework相关的通用函数,其中TEntity是EF实体对象&,而TKey往往是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);
    }
}

当最低起订量context.Setup(...时,出现以下错误:

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

你能帮忙吗?

谢谢。

UPDATE-1

这是我最初的调用,我尝试在其中直接从模拟设置中调用静态方法(扩展名):

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

我的模拟如下创建:

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

但是当调用时,出现以下错误:

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

更新2

如@Johnny所建议,我应该模拟该接口,因此我尝试了以下操作,但出现了相同的错误:

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,

我也没有调用包装器类,而是尝试直接从模拟对象调用UpdateCollection方法,因为它是在接口中定义的,即c => c.UpdateCollection(databaseCollection,...),但无济于事。 >

1 个答案:

答案 0 :(得分:1)

我最终使用@Johnny的建议方法使其工作,该方法是要模拟到接口,但我必须对我的模拟进行一点改动:

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

而不是通过

o=>o.Id.Value

我没有通过

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

请注意,尝试在我的原始代码(称为包装器类)中传递It.IsAny<Func<TestObject, int>>()无效,并引发以下异常:

System.InvalidOperationException: 'No coercion operator is defined 
between types 'Extensions.MyExtensionWapper' and 'Moq.Mock'.'