C# 如何使用AutoFixture.CreateAnonymous<&燃气轮机;()在具有内部ctor的类上

C# 如何使用AutoFixture.CreateAnonymous<&燃气轮机;()在具有内部ctor的类上,c#,unit-testing,autofixture,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-type

我做了如下的事情

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
,以便能够访问内部条形图,然后我做了:

var fixture = new Fixture();
fixture.Register(() => new Bar(fixture.CreateAnonymous<string>()));
var foo = fixture.CreateAnonymous<Foo>();
var fixture=newfixture();
fixture.Register(()=>新条(fixture.CreateAnonymous());
var foo=fixture.CreateAnonymous();
问题:

这是使用AutoFixture的“正确”方法还是有更好的方法

你就不能这样做吗

fixture.Inject(Bars.TypeOne.SimpleBar);

这都是公开的。不需要InternalsVisibleTo,我认为…

这段代码可以工作,因为您已经有了一个引用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);
var fixture=newfixture().Customize(新的AutoMoqCustomization());
夹具。注入(棒。类型一。SimpleBar);
var sut=fixture.CreateAnonymous();
sut.Should().NotBeNull();
sut.Bar.Should().NotBeNull();
sut.Bar.Should().Be(Bar.TypeOne.SimpleBar);

永远不要走
内部可视的道路
-不要让我开始列表,但它从系统的每个部分开始,包括所有测试助手

如果你绝对不能(仔细思考它)——大多数时候你把内部设备放在一个名字空间中,你就不会把它的一部分考虑成一个命名空间,这样它们就不会杂乱任何东西——例如XUndo.SDK和各种<代码>。我已经为我的雇主使用了内部< /代码>子命名空间,那么,管理这种只为测试而暴露的内容的正确方法就是。注意,它之所以有一个名称,是因为它(正确地)在中被称为反模式


现在,回答你的问题

  • 考虑将用户通常不需要的东西隐藏在单独的命名空间中
  • 切勿使用
    InternalsVisibleTo
  • 不要使用仅测试代码
  • 公开一个只在软件的内部(可能是
    DEBUG
    ?)版本中公开的工厂(但理想情况下,您可以在另一个命名空间中无条件地公开):

    然后像这样使用它:

    #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
    
    #如果仅包含用于测试的
    公开课事实
    {
    [事实]
    公开无效事实()
    {
    夹具=新夹具();
    fixture.Register((字符串名称)=>BarsForTestOnly.Create(名称));
    var anonymousBar=fixture.CreateAnonymous();
    }
    [事实]
    public void FactSyntax2()//只是上面事实的一个变体
    {
    夹具=新夹具();
    fixture.Register(barsfortely.Create);
    var anonymousBar=fixture.CreateAnonymous();
    }
    [事实]
    使用FromFactory()的公共无效
    {
    夹具=新夹具();
    fixture.Customize(x=>x.FromFactory(barsfortely.Create));
    var anonymousBar=fixture.CreateAnonymous();
    }
    #恩迪夫
    

    或者,要使您所拥有的一切正常工作,您可以:

    [Fact]
    public void UsingCtor()
    {
        Fixture fixture = new Fixture();
        fixture.Register( ( string name )=> new Bar( name ) );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }
    
    [事实]
    公共作废使用系数()
    {
    夹具=新夹具();
    fixture.Register((字符串名称)=>新条(名称));
    var anonymousBar=fixture.CreateAnonymous();
    }
    
    右侧方法是只测试被测系统的公共API。因此,InternalsVisibleTo充其量只是治疗症状,而不是疾病。你不能公开构造函数吗?@MarkSeemann:我可以,但是
    实例的所有可能值都列在
    静态类条
    中,所以不需要创建其他值Er实例…+ 1这是最有意义的,根据你的评论,只有允许的值是由<代码> Bar < /代码> + 1所知道的,另一个在名称空间中隐藏“事物”的替代方案是考虑使用接口作为一种访问修饰符本身:@ Mark Seemann:已经阅读并重视了文章中的洞察力,但是它没有合作。请注意这里的一种技术。(显然,在这种特定的情况下,它(在显式实现的接口上只有方法)只有在你得到一个对象的实例之后才变得有价值,这是OP之后的鸡)。
    [Fact]
    public void UsingCtor()
    {
        Fixture fixture = new Fixture();
        fixture.Register( ( string name )=> new Bar( name ) );
        var anonymousBar = fixture.CreateAnonymous<Bar>();
    }