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

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>() );
    }

基本消息是:



我很乐意为其提供具体的实现:
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答案的评论)这里的(公认做作)上下文是对大型“几乎完整系统”被测系统对象图的接受测试,而不是小的(受控/易于伪装的)对或三元组单元或集成测试方案中的类的集合。正如自我提问括号中提到的那样,尽管如此,我也不完全相信这种测试是有意义的。

最佳答案

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

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/

10-12 14:47