如何使用内部ctor在类上创建AutoFixture.CreateAnonymous<>()

时间:2012-04-25 16:19:14

标签: c# unit-testing autofixture

我做过类似下面的事情

public class Foo
{
    public Bar { get; set; }
}

public class Bar
{
    internal Bar(string id)
    {}
}

public static class Bars
{
     public static class TypeOne
     {
           public static readonly SimpleBar = new Bar("id-for-type1-simple-bar");
     }
}

现在,我在我的单元测试程序集中添加了一个InternalsVisibleTo,以便能够访问内部Bar ctor然后我做了:

var fixture = new Fixture();
fixture.Register(() => new Bar(fixture.CreateAnonymous<string>()));
var foo = fixture.CreateAnonymous<Foo>();

问题:
这是使用AutoFixture的“正确”方式还是有更好的方法?

3 个答案:

答案 0 :(得分:2)

难道你不能这样做吗?

fixture.Inject(Bars.TypeOne.SimpleBar);

这都是公开的。不需要InternalsVisibleTo,我想......

答案 1 :(得分:2)

此代码有效,因为您已经有一个引用Bar的公共静态类,这可以不设置InternalsVisibleTo属性

        var fixture = new Fixture().Customize(new AutoMoqCustomization());

        fixture.Inject(Bars.TypeOne.SimpleBar);

        var sut = fixture.CreateAnonymous<Foo>();

        sut.Should().NotBeNull();
        sut.Bar.Should().NotBeNull();
        sut.Bar.Should().Be(Bars.TypeOne.SimpleBar);

答案 2 :(得分:2)

永远不要走InternalsVisibleTo的道路 - 不要让我开始列表,但它从你的系统的每个部分开始,包括所有测试帮助者都是强名。

如果你绝对不能(想想很久很难 - 大多数情况下,你最好放置内部,你不会考虑将你的公共api部分放入命名空间,这样它们就不会混乱 - 例如Xunit .Sdk和我用于我的雇主的各种.Internal子命名空间,然后管理这种公开的仅仅测试的正确方法是For Tests Only的概念。注意这个名字的原因是它(正确地)被称为the xUnit Test Patterns book中的反模式。


现在,回答你的问题......

  1. 考虑隐藏用户通常不需要在单独的命名空间中使用的内容
  2. 永远不要使用InternalsVisibleTo
  3. 不要使用仅测试代码
  4. 公开一个只在内部(可能是DEBUG?)软件构建的工厂(但理想情况下,你可以在另一个名称空间中使用它):

    #if INCLUDE_FOR_TEST_ONLY
    public static class BarsForTestOnly
    {
        public static Bar Create( string id )
        {
            return new Bar( id );
        }
    }
    #endif
    

    并像这样使用它:

    #if INCLUDE_FOR_TEST_ONLY
    public class Facts
    {
    
    [Fact]
    public void Fact()
    {
        Fixture fixture = new Fixture();
        fixture.Register( ( string name ) => BarsForTestOnly.Create( name ) );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }
    
    [Fact]
    public void FactSyntax2() // Just a variant of Fact above
    {
        Fixture fixture = new Fixture();
        fixture.Register<string, Bar>( BarsForTestOnly.Create );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }
    
    [Fact]
    public void UsingFromFactory()
    {
        Fixture fixture = new Fixture();
        fixture.Customize<Bar>(  x=> x.FromFactory<string>( BarsForTestOnly.Create ) );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }
    #endif
    

    或者,要制作Just Work,您可以这样做:

    [Fact]
    public void UsingCtor()
    {
        Fixture fixture = new Fixture();
        fixture.Register( ( string name )=> new Bar( name ) );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }