【问题标题】:Mocking a method within a method with FakeItEasy使用 FakeItEasy 在方法中模拟方法
【发布时间】:2014-02-13 07:52:59
【问题描述】:

如何模拟/伪造在另一个函数中调用的函数的结果?通常 Test2 将是我不喜欢获取真实数据的 DataAccess 方法。 我喜欢我的 unittest 测试的是业务逻辑。

这就是我现在所拥有的,但它根本不起作用。 Sum 始终断言为 5!

public int Test1()
{
    var value = this.Test2(); //Unittest should substitute with 5
    var businesslogic = value + 10; //The business logic

    return businesslogic;
}

public int Test2()
{
    return 10; //I try to mock this value away in the test. Don´t go here!
}

然后我有一个单元测试,我想在我的“业务逻辑”上运行。

[TestMethod()]
public void TestToTest()
{
//Arrange
var instance = A.Fake<IClassWithMethods>();

      //Make calling Test2 return 5 and not 10.
A.CallTo(() => instance.Test2()).Returns(5);

      //Call the method 
var sum = instance.Test1();

//Assert if the business logic in the method works.
Assert.AreEqual(15, sum);
}

【问题讨论】:

    标签: c# unit-testing fakeiteasy


    【解决方案1】:

    据我所知,你不能这样做。

    您的instance 不是真实类的实例,只是其接口上的模型,因此对instance.Test1() 的调用不会调用您上面描述的代码。但是,您可以自己使用 UnitTest Test2 方法。

    但是,您可以做 2 个单元测试。

    在第一个测试(测试方法Test2)中,您使用必要的依赖项(或者如果没有具有某些值/参数的依赖项)实例化您的类。

    然后进行第二次测试,输入参数相同,测试Test() 方法。

    Mockups 仅用于必须在接口上模拟的依赖项(在您测试的类外部实例化)。即如果你有ClassAClassBClassA 取决于IClassB 接口。然后你可以模拟 B 来测试 A。

    【讨论】:

      【解决方案2】:

      首先,让我说,我认为Tseng's answer 中有一些很棒的观点,尤其是关于如何

      1. 伪造接口意味着永远不能调用“内部方法”,并且
      2. 你应该伪造依赖,而不是内部。如果您可以选择进行此更改,请执行此操作,并立即停止阅读我的回答。

      如果你还在阅读,我对两件事感到困惑:

      1. 应该Test1返回businessLogic吗?正如它所写的那样(一旦修复了编译错误),我希望Test1Test2 返回 5 时返回 5(而不是 15)。
      2. TestToTest 中,当你在Test2 上设置Returns(5),然后调用Test1,因为你伪造了一个接口,我希望 sum 为 0,即 int 的默认值。我不知道你怎么会得到 5。事实上,我在这个测试中复制了这种行为:

      [TestMethod]
      public void TestToTestInterface()
      {
          //Arrange
      
          var instance = A.Fake<IClassWithMethods>();
      
          //Make calling Test2 return 5 and not 10.
          A.CallTo(() => instance.Test2()).Returns(5);
      
          //Call the method 
          var sum = instance.Test1();
      
          //Assert if the business logic in the method works.
          Assert.AreEqual(0, sum); // because Test1 wasn't faked
      }
      

      虽然我自己并不关心这种方法,但如果您真的想在ClassWithMethods 中拥有可替换代码,然后测试Test1 方法,有一种方法:

      1. 我们需要制作Test1Test2 virtual,否则它们将无法伪造。
      2. 假冒ClassWithMethods,而不是IClasssWithMethods
      3. 告诉fake,当Test1被调用时,它应该调用原始代码(反过来又会调用fake Test2)。

      我已将这些更改全部放在一起,我的测试通过了:

      public class ClassWithMethods : IClassWithMethods
      {
          public virtual int Test1()
          {
              var value = this.Test2(); //Unittest should substitute with 5
              var businesslogic = value + 10; //The business logic
      
              return businesslogic;
          }
      
          public virtual int Test2()
          {
              return 10; //I try to mock this value away in the test. Don´t go here!
          }
      }
      
      [TestMethod]
      public void TestToTestClass()
      {
          //Arrange
      
          var instance = A.Fake<ClassWithMethods>();
      
          //Make calling Test2 return 5 and not 10.
          A.CallTo(() => instance.Test2()).Returns(5);
      
          // Make sure that Test1 on our fake calls the original ClassWithMethods.Test1
          A.CallTo(() => instance.Test1()).CallsBaseMethod();
      
          //Call the method 
          var sum = instance.Test1();
      
          //Assert if the business logic in the method works.
          Assert.AreEqual(15, sum);
      }
      

      【讨论】:

      • 很好的答案。我在问题中修复了我的代码以回答您的第一个问题。但是无论从这个确切的例子来看,我真正想要做的是能够在一个方法中测试逻辑而不调用在其中调用的其他方法。就像我在 Test2 中有一些插入到数据库中一样,我不想调用它方法,但我希望能够测试该方法的“值 + 10”部分的业务逻辑。我同意我不喜欢虚拟解决方案,改变方法似乎很激烈。
      • 如果您不想更改任何方法,那么我看不出您将如何完成您想要的那种测试。我和 Tseng 的建议都需要对代码进行一些修改,而 Tseng 的建议更具戏剧性(我认为更优秀)。如果您要避免修改代码,我认为您需要使用模拟框架,例如 TypeMock IsolatorMicrosoft Fakes
      • 非常感谢。 Microsoft Fakes 正是我正在寻找的东西。这是一个很好的开始使用它的链接codeproject.com/Articles/582812/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-31
      相关资源
      最近更新 更多