如何使用 FakeItEasy 伪造 Base Class 方法

How can I Fake Base Class method using FakeItEasy

我正在尝试使用 FakeItEasy。我有一个特定的场景,要么无法理解如何测试,要么无法使用 FakeItEasy

假设我有一个基础 class 和派生的 class 看起来像这样

public class BaseClass {
     protected bool BaseClassMethod() { return true; }
   }

public class DerivedClass : BaseClass {
     public void DoSomething(){
        if(BaseClassMethod()) Console.WriteLine("Bla");
        else Console.WriteLine("Worked");
  }
}

现在我希望能够测试 DerivedClass,但能够伪造 BaseClassMethod()。我尝试做类似

的事情
var fakeBaseClass = A.Fake<BaseClass>();
A.CallTo(fakedBaseClass).Where(x => x.Method.Name   "BaseClassMethod")).WithReturnType<bool>(). Returns(false); 
var derivedClass = new DerivedClass(); // Am hoping that the DerivedClass will use the Faked Baseclass that I have created above.
derivedClass.DoSomething()

这不符合我的预期。我是不是遗漏了什么或者 FakeItEasy 不可能做到这一点?

谢谢 卡尔提克

您的方法存在一些问题。

第一个问题是你创建的fakeBaseClassderivedClass之间没有任何联系,所以他们没有办法相互影响。为了完成我认为你正在尝试做的事情,你真的想制作一个假的 DerivedClass 并操纵它的行为(实际上,一般来说,这种类型的测试是有争议的,但让我们关注机制并搁置是否现在这是个好主意)。

通过伪造 DerivedClass,FakeItEasy 实际上将实例化一种新类型的 class, 派生自 DerivedClass,因此将调用和可以访问 DerivedClassBaseClass 的所有(受保护或 public)方法。然后你可以从 BaseClassMethod 设置你想要的行为并练习 DoSomething 并希望得到你想要的结果。

当我们尝试这个时会导致问题的第二件事是 BaseClassMethod 不是虚拟的。 FakeItEasy(及其同类的隔离框架)无法伪造任何非虚拟的方法。您可以在 What can be faked.

了解更多关于什么是可伪造的

因此,将这两个更改放在一起,我得到如下代码:

public class BaseClass
{
    protected virtual bool BaseClassMethod()
    {
        return true;
    }
}

public class DerivedClass : BaseClass
{
    public string DoSomething()
    {
        if (BaseClassMethod())
        {
            return ("Bla");
        }
        else
        {
            return ("Worked");
        }
    }
}

[Test]
public void MethodName_StateUnderTest_ExpectedBehavior()
{
    var fakedDerivedClass = A.Fake<DerivedClass>();
    A.CallTo(fakedDerivedClass)
        .Where(x => x.Method.Name == "BaseClassMethod")
        .WithReturnType<bool>()
        .Returns(false);

    Assert.That(fakedDerivedClass.DoSomething(), Is.EqualTo("Worked"));
}

本次测试通过。请注意,我已经对您的原件进行了更改(除了更正拼写错误):

  1. BaseClassMethod 现在是虚拟的
  2. 我正在创建一个假的 DerivedClass 用于测试,
  3. DoSomething returns 一个字符串,而不是写入控制台。这不是绝对必要的,但让我的测试更容易编写。

请注意,如果 BaseClassMethod 不是虚拟的,那么除了 true 之外,它不可能 return 任何东西,而且我认为编写测试没有多大意义看看 DoSomething 从中得到 false 会发生什么。

有关为什么伪造 class 被测者(而不是 class 的 合作者 )可能不是一个好主意的更多讨论,请参阅评论在 Use FakeItEasy's A.CallTo() on another method in same object and my answer to Using FakeItEasy, is it possible to create a dummy object of a type that takes generic type parameters.

但是您对这种方法的感受是您必须自己接受的。