C# 为什么Matching.ImplementedInterface的行为与Matching.ExactType和FrozenAttribute.As不同? 请考虑以下代码: 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. } } 公共类测试示例 { 公共类FactoryClass:类{} 公共类:IInterface{} 公共接口接口{} 公共类AutoData:AutoDataAttribute { public AutoData():base(Create()){} 静态iTexture创建() { var fixture=新fixture(); fixture.Customize(composer=>composer.FromFactory(()=>newfactoryclass()); fixture.Customize(composer=>composer.FromFactory(()=>newfactoryclass()); 返回夹具; } } [理论,测试样本,自动数据] public void OldSkool([freezed(As=typeof(IInterface))]Class-first,Class-second,IInterface-third) { IsType(第一个); 断言。相同(第一,第二); 断言。相同(第一,第三); } [理论,测试样本,自动数据] public void DirectBaseType([冻结(匹配.ExactType)]第一类,第二类) { IsType(第一个); 断言。相同(第一,第二); } [理论,测试样本,自动数据] public void ImplementedInterfaces([freezed(Matching.ImplementedInterfaces)]类第一,接口第二) { IsType(第一个); Assert.Same(第一个,第二个);//失败。 } }

C# 为什么Matching.ImplementedInterface的行为与Matching.ExactType和FrozenAttribute.As不同? 请考虑以下代码: 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. } } 公共类测试示例 { 公共类FactoryClass:类{} 公共类:IInterface{} 公共接口接口{} 公共类AutoData:AutoDataAttribute { public AutoData():base(Create()){} 静态iTexture创建() { var fixture=新fixture(); fixture.Customize(composer=>composer.FromFactory(()=>newfactoryclass()); fixture.Customize(composer=>composer.FromFactory(()=>newfactoryclass()); 返回夹具; } } [理论,测试样本,自动数据] public void OldSkool([freezed(As=typeof(IInterface))]Class-first,Class-second,IInterface-third) { IsType(第一个); 断言。相同(第一,第二); 断言。相同(第一,第三); } [理论,测试样本,自动数据] public void DirectBaseType([冻结(匹配.ExactType)]第一类,第二类) { IsType(第一个); 断言。相同(第一,第二); } [理论,测试样本,自动数据] public void ImplementedInterfaces([freezed(Matching.ImplementedInterfaces)]类第一,接口第二) { IsType(第一个); Assert.Same(第一个,第二个);//失败。 } },c#,autofixture,C#,Autofixture,正如您(希望)看到的,ImplementedInterfaces测试失败。由于FrozenAttribute.As已被弃用,并且已指示用户移动到匹配枚举,因此我希望它的行为与以前相同 但是,Match.implementedInterface的行为似乎与Match.ExactType和FrozenAttribute.As的行为有所不同 我做了一些探索,发现匹配。ExactType和FrozenAttribute。As使用种子请求规范,而匹配。实现的接口只匹配类型请求 有没有可能了解一下这种行为的

正如您(希望)看到的,
ImplementedInterfaces
测试失败。由于
FrozenAttribute.As
已被弃用,并且已指示用户移动到匹配枚举,因此我希望它的行为与以前相同

但是,
Match.implementedInterface
的行为似乎与
Match.ExactType
FrozenAttribute.As
的行为有所不同

我做了一些探索,发现
匹配。ExactType
FrozenAttribute。As
使用
种子请求规范
,而
匹配。实现的接口只匹配
类型
请求


有没有可能了解一下这种行为的背景?这是故意的吗?如果是这样的话,是否有一个已知的建议,以这样的方式设计,使用
Match.ImplementedInterfaces

首先,一个但书:OP中提供的代码在我的机器上,使用AutoFixture 3.39.0,行为与所描述的不完全一样。区别在于,此测试中的第一个断言通过了:

这是最好的实现方式吗?也许不是,但这就是它目前的工作方式。有人建议应该重构冻结实现,使其更像DI容器的单例生存期。这可能会改变此特定场景中的行为,使其更适合。我现在还不知道它是否也会有一些缺点

当我们重新设计
[freezed]
属性以使用更灵活的
匹配
规则时,我意识到新系统不能百分之百地替代旧的
As
属性。我仍然认为这种权衡是值得的

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

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

是否有已知的建议使用Match.ImplementedInterface以这种方式设计以恢复旧行为

是的,考虑简化测试系统(SUT)的设计。 AutoFixture最初被认为是一个测试驱动的开发工具,这仍然是它的主要用途。本着这样的精神,我们应该倾听测试。如果测试难以编写,第一反应应该是简化SUT。AutoFixture倾向于放大来自测试的反馈

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


马克·希曼(mark seemann),能不能简单一点呢?

答案非常全面(一如既往!)。非常感谢。关于但书/错误(标记)的失败测试,您确实是正确的。这是我在阅读结果时犯的一个错误(实际上没有点击该行进行验证)。要了解问题的核心,很可能是因为我仍然在学习TDD和测试,但与模拟一样,我喜欢使用工厂创建SUT(或支持对象)并在测试中使用它。这是这里的核心问题:从工厂创建一个项目并将其冻结(作为单例)。
[Theory, TestingSample.AutoData]
public void ImplementedInterfaces(
    [Frozen(Matching.ImplementedInterfaces)]Class first,
    IInterface second)
{
    Assert.IsType<FactoryClass>(first); // passes
    Assert.Same(first, second); // fails
}
[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
}