c# - 确保对象的所有实例都具有具有单元测试的抽象类的实现
问题描述
我正在尝试编写一个单元测试,以确保 Ardalis SmartEnum 的所有变体都具有相应的泛型类实现。
以枚举为例。
public sealed class DomainEntityEnum : SmartEnum<DomainEntityEnum, string>
{
public static readonly DomainEntityEnum Foo = new DomainEntityEnum(nameof(Foo), "Foo");
public static readonly DomainEntityEnum Bar = new DomainEntityEnum(nameof(Bar), "Bar");
public static readonly DomainEntityEnum Baz = new DomainEntityEnum(nameof(Baz), "Baz");
private DomainEntityEnum(string name, string value)
: base(name, value)
{
}
}
现在学习这个通用类
public interface IBaseDomainLocator
{
Task<int?> GetSomeItemId(IDbContext dbContext, DomainEntityEnum domainEntityEnum, int domainEntityResourceId);
}
abstract class BaseDomainLocator<T> : IBaseDomainLocator where T : DomainEntity
{
protected abstract DomainEntityEnum DomainEntity { get; }
protected virtual Expression<Func<T, bool>> IdFilter(int id) => q => q.GetAsResourceItemId().Id == id;
protected virtual Expression<Func<T, int?>> SomeItemSelector() => null;
public async Task<int?> GetSomeItemId(IDbContext dbContext, DomainEntityEnum domainEntityEnum, int domainEntityResourceId)
{
if (domainEntityEnum != DomainEntity)
return null;
if (SomeItemSelector() != null)
{
return await dbContext.Set<T>()
.Where(IdFilter(domainEntityResourceId))
.Select(SomeItemSelector())
.SingleOrDefaultAsync();
}
return null;
}
}
我们创建了一个目录,然后我们可以根据 DomainEntityEnum 的值获取特定的实例。
public static class DomainLocatorServiceMap
{
private static Dictionary<DomainEntityEnum, Type> sourceTypeToProviderKvps { get; }
static DomainLocatorServiceMap()
{
sourceTypeToProviderKvps = new Dictionary<DomainEntityEnum, Type>();
}
public static Type GetDomainLocatorType(DomainEntityEnum domainEntity)
{
sourceTypeToProviderKvps.TryGetValue(domainEntity, out Type domainLocator);
return domainLocator;
}
public static Type GetRequiredDomainLocatorType(DomainEntityEnum domainEntity)
=> sourceTypeToProviderKvps[domainEntity];
public static void AssociateWithScopedServiceBind<TService, TImplementation>(IServiceCollection services, DomainEntityEnum domainEntity)
where TService : class
where TImplementation : class, TService
{
services.AddScoped<TService, TImplementation>();
AssociateDomainLocator(domainEntity, typeof(TService));
}
private static void AssociateDomainLocator(DomainEntityEnum domainEntity, Type serviceType)
{
if (!typeof(IBaseDomainLocator).IsAssignableFrom(serviceType))
throw new Exception("IBaseDomainLocator invalid");
sourceTypeToProviderKvps[domainEntity] = serviceType;
}
}
public interface IDomainLocatorServiceCatalog
{
IBaseDomainLocator GetDomainLocatorService(DomainEntityEnum domainEntity);
}
class DomainLocatorServiceCatalog : IDomainLocatorServiceCatalog
{
private readonly IServiceProvider _serviceProvider = null;
public DomainLocatorServiceCatalog(IServiceProvider serviceProvider)
{
serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public IBaseDomainLocator GetDomainLocatorService(DomainEntityEnum domainEntity)
{
Type serviceType = DomainLocatorServiceMap.GetDomainLocatorType(domainEntity);
if (serviceType != null)
{
object service = _serviceProvider.GetRequiredService(serviceType);
IBaseDomainLocator domainLocator = (IBaseDomainLocator)service;
return domainLocator;
}
throw new Exception("Invalid Domain Entity");
}
}
实现看起来像这样
internal interface IBazDomainLocator : IBaseDomainLocator { }
class BazDomainLocator : BaseDomainLocator<Baz>, IBazDomainLocator
{
protected override DomainEntityEnum DomainEntity => DomainEntityEnum.Baz;
protected override Expression<Func<Baz, int?>> SomeItemSelector() => q => q.SomeItemId;
}
而这些都是通过依赖注入注册的
internal static class DomainFinderDependencyInjection
{
public static IServiceCollection AddDomainFinderServices(this IServiceCollection services)
{
DomainLocatorServiceMap.AssociateWithScopedServiceBind<IBazDomainLocator, BazDomainLocator>(services, DomainEntityEnum.Baz);
return services;
}
}
考虑到我需要 IServiceProvider 来查找 SmartEnum 值的域定位器的实现,我如何编写测试以确保枚举的所有值都具有 IBaseDomainLocator 的实现?使用 DomainEntityEnum.List 循环遍历枚举中包含的所有值非常容易,但我需要某种方法从服务提供商处解析 GetRequiredService(最好不必复制 DomainFinderDependencyInjection)
解决方案
推荐阅读
- arrays - 带有空格且元素中没有空格的 Bash 数组
- c# - 随机化位置
- c++ - . 可以有一个更简单的函数定义 - (to.string()) 下面
- javascript - 附加选项以选择不起作用。CSS对此负责吗?
- c++ - 在c ++中调用类指针的默认构造函数作为map的值
- laravel - 使用关系从 Laravel 中的第二个表中获取最小值
- python-3.x - 如何在 bs4 中对 find_all() 的标记进行部分调节?
- python - 在 OpenCV 中随图像移动的增强现实线
- r - 两组二进制变量的条形图?
- android - TextDecoration 不适用于 LazyColumn 项目