最小起订量 IServiceProvider/IServiceScope [英] Moq IServiceProvider / IServiceScope

查看:35
本文介绍了最小起订量 IServiceProvider/IServiceScope的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 IServiceProvider 创建一个 Mock(使用 Moq),以便我可以测试我的存储库类:

I am trying to create a Mock (using Moq) for an IServiceProvider so that I can test my repository class:

public class ApiResourceRepository : IApiResourceRepository
{
    private readonly IServiceProvider _serviceProvider;

    public ApiResourceRepository(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        _dbSettings = dbSettings;
    }

    public async Task<ApiResource> Get(int id)
    {
        ApiResource result;

        using (var serviceScope = _serviceProvider.
            GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            result = await
                context.ApiResources
                .Include(x => x.Scopes)
                .Include(x => x.UserClaims)
                .FirstOrDefaultAsync(x => x.Id == id);
        }

        return result;
    }
}

我尝试创建 Mock 对象如下:

My attempt at creating the Mock object is as follows:

Mock<IServiceProvider> serviceProvider = new Mock<IServiceProvider>();

serviceProvider.Setup(x => x.GetRequiredService<ConfigurationDbContext>())
    .Returns(new ConfigurationDbContext(Options, StoreOptions));

Mock<IServiceScope> serviceScope = new Mock<IServiceScope>();

serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);

serviceProvider.Setup(x => x.CreateScope()).Returns(serviceScope.Object);

我收到以下错误:

System.NotSupportedException : 表达式引用了一个方法不属于模拟对象:x =>x.GetRequiredService()

System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.GetRequiredService()

推荐答案

如前所述,Moq 不允许设置扩展方法.

As already stated, Moq does not allow setup of extension methods.

然而在这种情况下,上述扩展方法的源代码可在 Github 上获得

In this case however the source code of the said extension methods are available on Github

ServiceProviderServiceExtensions.

解决此类问题的通常方法是找出扩展方法的作用并安全地模拟路径执行.

The usual way around an issue like this is to find out what the extension methods do and mock a path safely through it's execution.

所有这些的基本类型是IServiceProvider 及其object Getservice(Type type) 方法.这个方法是解析服务类型时最终调用的方法.我们只处理抽象(接口),这使得使用 moq 变得更加容易.

The base type in all of this is the IServiceProvider and its object Getservice(Type type) method. This method is what is ultimately called when resolving the service type. And we are only dealing with abstraction (interfaces) then that makes using moq all the more easier.

//Arrange
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider
    .Setup(x => x.GetService(typeof(ConfigurationDbContext)))
    .Returns(new ConfigurationDbContext(Options, StoreOptions));

var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);

var serviceScopeFactory = new Mock<IServiceScopeFactory>();
serviceScopeFactory
    .Setup(x => x.CreateScope())
    .Returns(serviceScope.Object);

serviceProvider
    .Setup(x => x.GetService(typeof(IServiceScopeFactory)))
    .Returns(serviceScopeFactory.Object);

var sut = new ApiResourceRepository(serviceProvider.Object);

//Act
var actual = sut.Get(myIntValue);

//Asssert
//...

查看上面的代码,您会看到这种安排如何满足扩展方法的预期行为,并通过扩展(无双关语)测试方法.

Review the code above and you would see how the arrangement satisfies the expected behavior of the extension methods and by extension (no pun intended) the method under test.

这篇关于最小起订量 IServiceProvider/IServiceScope的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆