使用FakeItEasy在方法中模拟方法

时间:2014-02-12 16:34:26

标签: c# unit-testing fakeiteasy

如何从另一个函数中调用的函数模拟/解析结果?通常,Test2将是一个DataAccess方法,我不想获取实际数据。 我喜欢我测试的单元测试是业务逻辑。

这就是我现在所拥有的,但它根本不起作用。 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!
}

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

[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);
}

2 个答案:

答案 0 :(得分:3)

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

你的instance不是真实类的实例,只是它界面上的一个模型,因此对instance.Test1()的调用不会调用你上面描述的代码。但是你可以使用UnitTest Test2方法。

然而,您可以做的是进行2次单元测试。

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

然后使用相同的输入参数和Testing Test()方法进行第二次测试。

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

答案 1 :(得分:3)

首先,我要说我认为Tseng's answer中存在很多奇点,特别是关于如何

  1. 伪造接口意味着永远不能调用“内部方法”,
  2. 你应该假装依赖,而不是内部。如果您可以选择进行此更改,请立即停止阅读我的答案。
  3. 如果你还在读书,我对两件事感到困惑:

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

    3. [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. 告诉假人,当调用Test1时,它应该调用原始代码(它将依次调用假Test2)。
      4. 我把所有这些变化放在一起,这个测试通过了我:

        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);
        }