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

本文关键字:CreateAnonymous AutoFixture 内部 何使用 ctor | 更新日期: 2023-09-27 18:32:18

我做了如下事情

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的"正确"方法还是有更好的方法?

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

你不能做这样的事情吗?

fixture.Inject(Bars.TypeOne.SimpleBar);

这都是公开的。不需要内部可见,我认为...

此代码有效,因为您已经有一个引用 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);
永远不要

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

如果你绝对不能(仔细想想 - 大多数时候你最好把你不认为是公共 API 一部分的内部结构放入命名空间中,这样它们就不会弄乱任何东西 - 例如 Xunit.Sdk 和我为我的雇主使用的各种.Internal子命名空间),那么管理这种仅用于测试的东西暴露的正确方法是仅用于测试的概念。注意,它之所以有名字,是因为它(正确地)在xUnit测试模式一书中被称为反模式。


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

  1. 考虑将用户通常不需要的内容隐藏在单独的命名空间中
  2. 切勿使用InternalsVisibleTo
  3. 不要使用仅测试代码

公开仅在内部公开的工厂(也许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

或者,要使你拥有的东西正常工作,你可以做:

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