派生类新方法应该覆盖但不是

时间:2012-07-22 19:28:30

标签: c# unit-testing

如果有一个解决方案,如果没有使基类方法虚拟并且派生方法被标记为覆盖,那就好奇了:

我希望它跳转到派生方法,将属性设置为true(出于测试目的,几乎就像这是一个模拟),但它跳进了基类。唯一的解决方案是使基础虚拟,我认为我可以在派生中将其标记为新的,并且可以工作。

   public class SomeClass
   {
      private readonly IFoo _foo;

      public SomeClass(IFoo foo)
      {
         _foo = foo;
      }

      public void DoSomething()
      {
         _foo.DoFoo();
      }
   }

   public interface IFoo
   {
      void DoFoo();
   }

   public class Foo : IFoo
   {
      public void DoFoo()
      {

      }
   }

   public class Foo2 : Foo
   {
      public bool DoFooWasCalled { get; set; }

      public new void DoFoo()
      {
         DoFooWasCalled = true;
         base.DoFoo();
      }
   }

这是失败的测试:

   [TestFixture]
   public class TestingCSInheritance
   {
      [Test]
      public void TestMethod()
      {
         var foo = new Foo2();
         var someClass = new SomeClass(foo);
         someClass.DoSomething();
         foo.DoFooWasCalled.ShouldBe(true);
      }
   }

我的猜测是因为我正在使用依赖注入接口,它正在使用基类,但我不确定原因。

2 个答案:

答案 0 :(得分:4)

  

唯一的解决方案是使基础虚拟化,我认为我可以在派生中将其标记为新的并且可以工作。

没有。如果您创建一个新方法,代码知道编译时类型Foo2的表达式将调用Foo2.DoSomething

即使TestMethod知道fooFoo2SomeClass.DoSomething只知道它为IFoo,所以它只是使用IFoo实施。 Foo2.DoSomething 不是 IFoo的实现。

你想要多态,但你已经通过不使用虚方法有效地丢弃了它。

唯一的另一个选择是在Foo2中重新实现 IFoo,这是谢尔盖描述的解决方案。请注意,最终会出现一些令人困惑的代码。几乎总是隐藏任何类型的方法。从根本上说,如果你想要虚拟方法的效果,你应该使用虚方法......

或者,如果使用合成而不是继承,它会更清晰:

public class MockFoo : IFoo
{
    private readonly Foo foo = new Foo();
    private bool doSomethingWasCalled;

    public void DoSomething()
    {
        doSomethingWasCalled = true;
        foo.DoSomething();
    }
}

委派DoSomething的调用,而不是试图兼顾继承层次结构。

答案 1 :(得分:1)

尝试更改Foo2声明:

public class Foo2 : Foo, IFoo