gpt4 book ai didi

c# - AutoFixture:配置开放式泛型样本生成器

转载 作者:太空狗 更新时间:2023-10-29 20:08:13 26 4
gpt4 key购买 nike

我有一个使用开放泛型的对象模型(是的,是的,现在我有两个问题;这就是我来这里的原因:) :-

public interface IOGF<T>
{
}

class C
{
}

class D
{
readonly IOGF<C> _ogf;

public D( IOGF<C> ogf )
{
_ogf = ogf;
}
}

我正在尝试让 AutoFixture 生成 D 的匿名实例多于。但是,就其本身而言,AutoFixture 没有构建 IOGF<> 的内置策略。因此我们观察到:

public class OpenGenericsBinderDemo
{
[Fact]
public void X()
{
var fixture = new Fixture();

Assert.Throws<Ploeh.AutoFixture.ObjectCreationException>( () =>
fixture.CreateAnonymous<D>() );
}

底层消息是:

Ploeh.AutoFixture.ObjectCreationException : AutoFixture was unable to create an instance from IOGF`1[C], most likely because it has no public constructor, is an abstract or non-public type.

我很乐意为它提供一个具体的实现:

public class OGF<T> : IOGF<T>
{
public OGF( IX x )
{
}
}

public interface IX
{
}

public class X : IX
{
}

和关联的绑定(bind):

fixture.Register<IX,X>();

我如何(或者我应该这样看待问题??)让下面的测试通过?

public class OpenGenericsLearning
{
[Fact]
public void OpenGenericsDontGetResolved()
{
var fixture = new Fixture();
fixture.Inject<IX>( fixture.Freeze<X>() );

// TODO register or do something that will provide
// OGF<C> to fulfill D's IOGF<C> requirement

Assert.NotNull( fixture.CreateAnonymous<D>());
}
}

(在 codeplex 站点上有关于此的讨论和问题 - 我只需要快速实现这一点,如果这只是一个坏主意和/或我错过了一些东西,我愿意删除它)

编辑 2:(另请参阅对 Mark 的回答的评论)这里的(公认的人为的)上下文是对大型“几乎完整系统”的被测系统对象图而不是小型(受控/易于理解 :) 的验收测试单元或集成测试场景中的一对或三组类。正如在 self 提问的附加陈述中提到的,我并不完全相信这种类型的测试是否有意义。

最佳答案

您可以创建一个按如下方式工作的自定义:

public class AnOpenGenericsBinderDemo
{
[Fact]
public void RegisteringAGenericBinderShouldEnableResolution()
{
var fixture = new Fixture();
fixture.Inject<IX>( fixture.Freeze<X>() );
fixture.RegisterOpenGenericImplementation( typeof( IOGF<> ), typeof( OGF<> ) );

Assert.IsType<OGF<C>>( fixture.CreateAnonymous<D>().Ogf );
}
}

并且是这样实现的:

public static class AutoFixtureOpenGenericsExtensions
{
public static void RegisterOpenGenericImplementation( this IFixture that, Type serviceType, Type componentType )
{
if ( !serviceType.ContainsGenericParameters )
throw new ArgumentException( "must be open generic", "serviceType" );
if ( !componentType.ContainsGenericParameters )
throw new ArgumentException( "must be open generic", "componentType" );
// TODO verify number of type parameters is 1 in each case
that.Customize( new OpenGenericsBinderCustomization( serviceType, componentType ) );
}

public class OpenGenericsBinderCustomization : ICustomization
{
readonly Type _serviceType;
readonly Type _componentType;

public OpenGenericsBinderCustomization( Type serviceType, Type componentType )
{
_serviceType = serviceType;
_componentType = componentType;
}

void ICustomization.Customize( IFixture fixture )
{
fixture.Customizations.Add( new OpenGenericsSpecimenBuilder( _serviceType, _componentType ) );
}

class OpenGenericsSpecimenBuilder : ISpecimenBuilder
{
readonly Type _serviceType;
readonly Type _componentType;

public OpenGenericsSpecimenBuilder( Type serviceType, Type componentType )
{
_serviceType = serviceType;
_componentType = componentType;
}

object ISpecimenBuilder.Create( object request, ISpecimenContext context )
{
var typedRequest = request as Type;
if ( typedRequest != null && typedRequest.IsGenericType && typedRequest.GetGenericTypeDefinition() == _serviceType )
return context.Resolve( _componentType.MakeGenericType( typedRequest.GetGenericArguments().Single() ) );
return new NoSpecimen( request );
}
}
}
}

我假设有人有比这更好的实现和/或有一个内置的实现。

编辑:以下是具有传感属性的更新 D:

class D
{
readonly IOGF<C> _ogf;

public D( IOGF<C> ogf )
{
_ogf = ogf;
}

public IOGF<C> Ogf
{
get { return _ogf; }
}
}

关于c# - AutoFixture:配置开放式泛型样本生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10092446/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com