如何解决如何为没有公共构造函数的密封类创建固定装置?
我密封了一个没有构造函数的类,这是我使用 SDK 引用到我的项目。我想为类创建夹具数据来编写测试,但 AutoFixture 给出了如下期望。
AutoFixture was unable to create an instance from SealedTypeclass,most likely because it has no public constructor,is an abstract or non-public type.
请找到我正在尝试为其创建夹具的以下代码示例。
public sealed class TokenCacheItem
{
public string Authority { get; }
public string ClientId { get; }
public DateTimeOffset ExpiresOn { get; }
public string FamilyName { get; }
public string Givenname { get; }
public string IdentityProvider { get; }
public string TenantId { get; }
}
对于上面密封的类,我是通过 SDK 引用的,我正在尝试创建夹具数据。我收到以下错误消息。
留言: AutoFixture.ObjectCreationExceptionWithPath :AutoFixture 无法从 *** 创建实例,很可能是因为它没有公共构造函数,是抽象或非公共类型。
任何通用的解决方案?
解决方法
鉴于它是密封的并报告它没有公共构造函数,您将不得不提供一种创建实例的方法,它可能是基于反射的解决方案。只读属性也增加了 AutoFixture 的复杂性。
没有看到构造函数,或者只读属性是否有任何支持字段,我将通过以下工作示例做出一些假设。
创建可以创建 TokenCacheItem
并设置其属性的内容:
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority,value); }
public string ClientId { get => _tokenCacheItem.ClientId; set => SetPropertyValue(x => x.ClientId,value); }
public DateTimeOffset ExpiresOn { get => _tokenCacheItem.ExpiresOn; set => SetPropertyValue(x => x.ExpiresOn,value); }
public string FamilyName { get => _tokenCacheItem.FamilyName; set => SetPropertyValue(x => x.FamilyName,value); }
public string GivenName { get => _tokenCacheItem.GivenName; set => SetPropertyValue(x => x.GivenName,value); }
public string IdentityProvider { get => _tokenCacheItem.IdentityProvider; set => SetPropertyValue(x => x.IdentityProvider,value); }
public string TenantId { get => _tokenCacheItem.TenantId; set => SetPropertyValue(x => x.TenantId,value); }
public MutableTokenCacheItem()
{
var ctor = typeof(TokenCacheItem).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Single();
_tokenCacheItem = (TokenCacheItem)ctor.Invoke(null);
}
private void SetPropertyValue<P>(Expression<Func<TokenCacheItem,P>> expression,object value)
{
var body = expression.Body as MemberExpression;
var backingField = typeof(TokenCacheItem).GetRuntimeFields().Where(a => Regex.IsMatch(a.Name,$"\\A<{body.Member.Name}>k__BackingField\\Z")).Single();
backingField.SetValue(_tokenCacheItem,value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
创建一个样本构建器以将其很好地固定到 AutoFixture 中:
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request,ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
添加自定义,然后开始:
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
fixture.Create<TokenCacheItem>();
工作 LINQPad 示例:
void Main()
{
var fixture = new Fixture();
fixture.Customizations.Add(new TokenCacheItemSpecimenBuilder());
Console.Write(fixture.Create<TokenCacheItem>());
}
public class TokenCacheItemSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request,ISpecimenContext context)
{
var t = request as Type;
if (typeof(TokenCacheItem).Equals(t))
{
var mutableTokenCacheItem = context.Create<MutableTokenCacheItem>();
return mutableTokenCacheItem.AsImmutableTokenCacheItem();
}
return new NoSpecimen();
}
}
public class MutableTokenCacheItem
{
private TokenCacheItem _tokenCacheItem;
public string Authority { get => _tokenCacheItem.Authority; set => SetPropertyValue(x => x.Authority,value);
}
public TokenCacheItem AsImmutableTokenCacheItem()
{
return _tokenCacheItem;
}
}
public sealed class TokenCacheItem
{
public string Authority { get; }
public string ClientId { get; }
public DateTimeOffset ExpiresOn { get; }
public string FamilyName { get; }
public string GivenName { get; }
public string IdentityProvider { get; }
public string TenantId { get; }
private TokenCacheItem() { }
}
结果:
YMMV 取决于实际的 TokenCacheItem
实现,尽管它可能不远了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。