如何使用FakeItEasy伪造基类方法

时间:2015-02-20 19:16:32

标签: mocking fakeiteasy

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

假设我有一个基类和派生类,看起来像这样

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无法做到这一点?

由于 KARTHIK

1 个答案:

答案 0 :(得分:1)

您的方法存在一些问题。

第一个问题是,您创建的fakeBaseClassderivedClass之间没有联系,因此他们无法相互影响。要完成我认为你想要做的事情,你真的想制造一个假的DerivedClass并操纵它的行为(实际上,一般来说,这种类型的测试是有争议的,但让我们关注机制并留出是否现在这是一个好主意)。

通过伪造DerivedClass,FakeItEasy实际上将实例化派生自DerivedClass 的新类型,因此将调用并访问所有(受保护或公共) DerivedClassBaseClass的方法。然后,您可以根据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返回一个字符串,而不是写入控制台。这不是绝对必要的,但让我的测试更容易编写。
  4. 请注意,如果BaseClassMethod不是虚拟的,那么除了true之外,它不会返回任何其他内容,我在编写测试时看不到有什么意义,看看在DoSomething时会发生什么{1}}从中获取false

    有关为什么伪造受测试的课程(而不是该课程的协作者)的更多讨论可能不是一个好主意,请参阅对Use FakeItEasy's A.CallTo() on another method in same object的评论以及我对Using FakeItEasy, is it possible to create a dummy object of a type that takes generic type parameters的回答

    但是你对这种方法的看法是你必须自己接受的。