gpt4 book ai didi

c# - 为什么 Matching.ImplementedInterfaces 的行为与 Matching.ExactType 和 FrozenAttribute.As 不同?

转载 作者:行者123 更新时间:2023-12-03 19:38:19 30 4
gpt4 key购买 nike

请考虑以下代码:

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 使用了 SeedRequestSpecificationMatch. ImplementedInterfaces 仅匹配 Type 请求。

是否有可能获得有关此行为的一些背景信息?这是设计使然吗?如果是这样,是否有已知的建议来设计,以使用 Match.ImplementedInterfaces 恢复旧行为?

最佳答案

首先,附带条件:在我的机器上,使用 AutoFixture 3.39.0,OP 中提供的代码的行为完全与描述不符。不同之处在于,此测试中的第一个断言通过了:

[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 根本没有卡住!

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

[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
}

这是最好的实现吗?也许不是,但这就是目前的运作方式。有an open issue in the AutoFixture GitHub repository建议应该重构 freeze 实现,使其更像 DI 容器的 Singleton 生命周期。这可能会将这种特定场景中的行为改变为更适合它的行为。它是否也会有一些缺点,目前我还无法判断。

当我们重新设计[Frozen]属性以使用更灵活的Matching规则时,我意识到新系统无法100%替换旧的 As 属性。我仍然认为这种权衡是值得的。

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

您可能会说 As 更灵活,但这主要是因为它没有内置智能。您也可以编写 [Frozen(As = typeof(IAsyncResult))] 并且可以很好地编译 - 只是在运行时失败,因为它完全是无意义的。

is there a known recommendation to design in such a way to restore the old behavior using Match.ImplementedInterfaces?

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

AutoFixture 最初被设想为测试驱动开发工具,这仍然是其主要目的。本着GOOS的精神,我们应该听测试。如果测试很难编写,第一 react 应该是简化 SUT。 AutoFixture 往往会放大来自测试的此类反馈。

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

能不能再简单一点?

关于c# - 为什么 Matching.ImplementedInterfaces 的行为与 Matching.ExactType 和 FrozenAttribute.As 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34840015/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com