c# – AutoFixture:配置Open Generics Specimen Builder

我有一个使用Open Generics的对象模型(是的,是的,现在我有两个问题;这就是为什么我在这里:): –
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
{
}

以及相关的绑定:

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的回答评论)这里(公认的设计)上下文是对一个大的“几乎完整的系统”系统测试对象图而不是一个小的(受控/易于理解:)对或三元组的验收测试单元或集成测试场景中的类.正如在自我问题括号中所提到的那样,我并不完全相信这种类型的测试甚至有意义.

解决方法

您可以创建一个自定义,其工作方式如下:
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; }
    }
}

相关文章

原文地址:http://msdn.microsoft.com/en-us/magazine/cc163...
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采...
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下...
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Mic...
c语言输入成绩怎么判断等级
字符型数据在内存中的存储形式是什么