首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Matching.ImplementedInterfaces的行为不同于Matching.ExactType和FrozenAttribute.As?

为什么Matching.ImplementedInterfaces的行为不同于Matching.ExactType和FrozenAttribute.As?
EN

Stack Overflow用户
提问于 2016-01-17 15:22:39
回答 1查看 271关注 0票数 2

请考虑以下代码:

代码语言:javascript
复制
public class TestingSample
{
    public class FactoryClass : Class {}

    public class Class : IInterface {}

    public interface IInterface {}

    public class AutoData : AutoDataAttribute
    {
        public AutoData() : base( Create() ) {}

        static IFixture Create()
        {
            var fixture = new Fixture();
            fixture.Customize<IInterface>( composer => composer.FromFactory( () => new FactoryClass() ) );
            fixture.Customize<Class>( composer => composer.FromFactory( () => new FactoryClass() ) );
            return fixture;
        }
    }

    [Theory, TestingSample.AutoData]
    public void OldSkool( [Frozen( As = typeof(IInterface) )]Class first, Class second, IInterface third )
    {
        Assert.IsType<FactoryClass>( first );
        Assert.Same( first, second );
        Assert.Same( first, third );
    }

    [Theory, TestingSample.AutoData]
    public void DirectBaseType( [Frozen( Matching.ExactType )]Class first, Class second )
    {
        Assert.IsType<FactoryClass>( first );
        Assert.Same( first, second );
    }

    [Theory, TestingSample.AutoData]
    public void ImplementedInterfaces( [Frozen( Matching.ImplementedInterfaces )]Class first, IInterface second )
    {
        Assert.IsType<FactoryClass>( first );
        Assert.Same( first, second ); // The Fails.
    }
}

正如您(希望)所看到的,ImplementedInterfaces测试失败了。由于FrozenAttribute.As已被废弃,并且用户被指示移动到Match枚举,我的期望是它的行为将与以前一样。

但是,Match.ImplementedInterfaces的行为似乎与Match.ExactTypeFrozenAttribute.As都不一样。

我确实做了一些探索,并看到Match.ExactTypeFrozenAttribute.As使用SeedRequestSpecification,而Match.ImplementedInterfaces只匹配Type请求。

是否有可能在这种行为上建立一些背景?这是故意的吗?如果是这样的话,是否有已知的设计建议来使用Match.ImplementedInterfaces恢复旧的行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-23 17:45:07

首先,附带条件:在我的机器上,使用AutoFixture 3.39.0,OP中提供的代码的行为不像描述的那样。不同的是,这个测试中的第一个断言通过了:

代码语言:javascript
复制
[Theory, TestingSample.AutoData]
public void ImplementedInterfaces(
    [Frozen(Matching.ImplementedInterfaces)]Class first,
    IInterface second)
{
    Assert.IsType<FactoryClass>(first); // passes
    Assert.Same(first, second); // fails
}

不过,我承认第二个断言失败(有点)令人吃惊。

简短的解释是,对于当前的实现,冻结是在反射时完成的,而不是在运行时完成的。当AutoFixture.Xunit2确定要冻结什么时,它会查看应用[Frozen]属性的参数的类型。这是Class,而不是FactoryClass,所以结果是FactoryClass根本没有冻结!

您可以从这个测试中看出这一点:

代码语言:javascript
复制
[Theory, TestingSample.AutoData]
public void FactoryClassIsNotFrozen(
    [Frozen(Matching.ImplementedInterfaces)]Class first,
    FactoryClass second)
{
    Assert.IsType<FactoryClass>(first); // passes
    Assert.IsType<FactoryClass>(second); // passes
    Assert.Same(first, second); // fails
}

这是最好的实现吗?也许不是,但这是目前的工作方式。有AutoFixture GitHub存储库中的一个未决问题建议应该重构冻结实现,使其更像DI容器的Singleton生存期。这可能会改变这种特殊情况下的行为,使之更适合这种情况。它是否也会有一些缺点,我现在还不能判断。

当我们重新设计[Frozen]属性以使用更灵活的Matching规则时,我意识到新系统无法100%地替代旧的As属性。我还是觉得这样的交易是值得的。

虽然As使您能够让这个特定特性工作,但这是因为作为程序员,您知道Class实现了IInterface,因此[Frozen(As = typeof(IInterface))]注释是有意义的。

你可以说As更灵活,但这主要是因为它没有内置的智能。你也可以编写[Frozen(As = typeof(IAsyncResult))],它编译得很好,但在运行时失败了,因为这完全是胡说八道。

是否有已知的使用Match.ImplementedInterfaces来恢复旧行为的设计建议?

是的,考虑简化测试系统(SUT)的设计。

AutoFixture最初被认为是一个测试驱动的开发工具,而这仍然是它的主要目的。本着古斯的精神,我们应该的测试。如果测试很难写,第一个反应应该是简化SUT。AutoFixture倾向于从测试中放大这种反馈。

您真的需要匹配既实现接口又从基类派生的东西吗?为什么?

能让它更简单吗?

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34840015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档