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
}