c# – 为什么这个继承的Establish多次执行?
我的理解是每个Establish只应执行一次,但下面的代码显示它执行多次.我们正在嵌套类以提供一些分组,同时在一个文件中保持Subject的单元测试.这似乎是一个错误.
我们正在使用machine.specifications.runner.resharper Reshaper扩展和MSpec 0.9.1. [Subject(typeof(string))] internal class EstablishRunTwice { Establish sharedContext = () => Console.WriteLine("Shared context"); internal class ScenarioA : EstablishRunTwice { Establish scenarioAContext = () => Console.WriteLine("ScenarioA context"); internal class ScenarioAVariation1 : ScenarioA { Because of = () => Console.WriteLine("ScenarioAVariation1 Because"); It it1 = () => Console.WriteLine("ScenarioAVariation1 It1"); It it2 = () => Console.WriteLine("ScenarioAVariation1 It2"); } internal class ScenarioAVariation2 : ScenarioA { Because of = () => Console.WriteLine("ScenarioAVariation2 Because"); It it1 = () => Console.WriteLine("ScenarioAVariation2 It1"); It it2 = () => Console.WriteLine("ScenarioAVariation2 It2"); } } internal class ScenarioB : EstablishRunTwice { Establish context = () => Console.WriteLine("ScenarioB context"); Because of = () => Console.WriteLine("ScenarioB Because"); It it1 = () => Console.WriteLine("ScenarioB It1"); It it2 = () => Console.WriteLine("ScenarioB It2"); } } 结果是ScenarioAVariation1的结果: Shared context Shared context ScenarioA context Shared context Shared context ScenarioA context ScenarioAVariation1 Because ScenarioAVariation1 It1 ScenarioAVariation1 It2 当我们使用NUnit进行自己的自定义上下文规范框架时,我们通过确保所有子类都是抽象的(在这种情况下,EstablishRunTwice和ScenarioA将是抽象的)来解决运行NUnit的问题,但MSpec在尝试这样做时抛出错误. 解决方法
这是构建事物的一种非常令人困惑的方式 – 聪明,但也许有点过于聪明.我发现很难阅读和理解意图.事实上,我甚至无法想象编译器会对继承结构做什么,因此我无法理解其意图.我想也许你在想这个.
所以让我看看,ScenarioA不仅嵌套在EstablishRunTwice中,而且还从它继承.这是否意味着它一直继承自身的嵌套副本到无穷大?然后,ScenarioB继承了所有这些!我的脑袋爆炸了.你得到令人困惑的结果我并不感到惊讶.嵌套真的给你什么?它是否使代码更易读或更易于维护?我不相信它确实如此. 使用KISS原则.正常的做法是将每个上下文放在自己的类中,不嵌套;只需使用文件对相关测试进行分组,您也可以使用[Subject]属性中的Concern参数作为另一种分组方式.如果有意义的话,你可以从其他上下文继承,但是在使用MSpec几年之后,我慢慢得出结论,过多的继承会损害可读性并使测试代码更加粘稠,所以明智地使用继承. 更新:反思我认为你想要实现的更长时间,我怀疑你正试图重新发明行为.这可能是MSpec的一个记录和理解不佳的特性,它允许您定义一组可以在以后在多个测试上下文中应用的常见行为.这听起来像你想要实现的那样吗?以下是行为的示例: [Behaviors] internal class DenebRightAscension { It should_have_20_hours_ = () => UUT.Degrees.ShouldEqual(20u); It should_have_41_minutes = () => UUT.Minutes.ShouldEqual(41u); It should_have_59_seconds = () => UUT.Seconds.ShouldEqual(59u); protected static Bearing UUT; } [Subject(typeof(HourAngle),"sexagesimal")] internal class when_converting_hour_angle_to_sexagesimal { Because of = () => { RaDeneb = 20.6999491773451; UUT = new Bearing(RaDeneb); }; Behaves_like<DenebRightAscension> deneb; protected static Bearing UUT; static double RaDeneb; } [Subject(typeof(Bearing),"sexagesimal")] internal class when_converting_to_sexagesimal { Because of = () => { RaDeneb = 20.6999491773451; UUT = new Bearing(RaDeneb); }; Behaves_like<DenebRightAscension> deneb; protected static Bearing UUT; static double RaDeneb; } 请注意,行为字段按名称匹配,而不是任何类型的继承.所以这种行为神奇地知道’UUT’的意思,即使这些类没有任何关系. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |