【问题标题】:how can mocking two methods on depend in the class如何在类中模拟两个方法依赖
【发布时间】:2011-12-16 23:17:12
【问题描述】:
interface ISample
{
    int Sum(int a,int b);
    int Multiplication(int x,int a,int b);
}

class Sample
{
    public int Sum(int a,int b)
    {
        return a+b;
    }

    public int Multiplication(int x,int a,int b)
   {
       return x*Sum(a,b);
   }
}

我想测试乘法方法。但是要测试 Multiplication 的方法, sum 方法需要模拟。我如何模拟 Sum 方法?有没有可能是这样的?

【问题讨论】:

  • 您不需要模拟任何东西 - 模拟 ISample 仅在依赖于它的类中才需要。
  • @Lee 这里的方法有依赖关系。

标签: c# unit-testing mocking moq


【解决方案1】:

我会独立测试 Sum,对于乘法测试,假设 Sum 有效。如果它适用于 Sum 测试,它也应该适用于乘法。此外,有些人会争辩说,乘法是如何做的,不应该被测试知道。如果以后有不依赖于 Sum 的不同算法怎么办?

【讨论】:

    【解决方案2】:

    你不模拟你正在测试的类,你模拟它所依赖的类。

    如果您真的希望能够独立于 Sum() 方法来测试 Multiplication() 方法,则必须将其分离到自己的接口中,并为 Sample 类提供该接口的实例,它可以用来进行求和。

    另一种方法是先简单地测试 Sum() 方法。如果 Sum() 方法通过了所有的测试,那么您可以合理地确定它可以正常工作。一旦您知道它可以正常工作,就可以通过测试 Multiplication() 方法来构建该知识。

    【讨论】:

    • 好答案,根据建议的替代方案-实际上不可能首先测试某些东西(除非它是在相同的测试方法中完成的)-因为永远不能保证测试的执行顺序。
    • 是的,你完全正确 - 我的意思是先编写 Sum 方法的测试,然后再编写 Multiplication 方法的测试。 (当然,即使在这种情况下,理论上 Sum 方法仍有可能中断,导致乘法测试失败,但至少你希望 Sum 测试也失败)
    【解决方案3】:

    正如其他人所说,您可以使用单独的接口。例如

    interface ISum{
    
       int Sum(int a, int b);
    }
    
    interface ISample
    {
        int Multiplication(int x, int a, int b);
    }
    
    public class Sample : ISample
    {
       ISum _sum;
        public Sample(ISum sum)
        {
          _sum = sum;
        }
    
       int Multiplication(int x, int a, int b)
       {
           return x*_sum.Sum(a,b);
       }
    }
    

    在您的测试代码中:

    [TestFixture]
    public class TestSample
    {
        [Test]
        public void TestSample()
        {
            var mockSum = new Mock<ISum>();
            mockSum.Setup(); // fill this what you want
            var sampleObj = new SampleObj(mockSum.Object);
            //Do Some Asserts
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      与其尝试在Multiplication 中“模拟”对Sum 的调用,不如简单地对其进行独立测试,因为对Sum 的调用是一个实现细节。但是,如果您的实际代码稍微复杂一些,您可以添加一个采用 Func 的重载:

      public int Multiplication(int x,int a,int b)
      {
          return this.Multiplication(x, a, b, (a, b) => a + b);
      }
      
      public int Multiplication(int x,int a,int b, Func<int, int, int> sumFunc)
      {
          return x * sumFunc(a, b);
      }
      

      然后,您可以在测试中提供自己的 sumFunc 实例。

      或者,您可以将 Sum 设为虚拟并在需要将其替换为您自己的实现的测试方法中覆盖它。

      【讨论】:

        【解决方案5】:

        另一个建议是显式实现接口 - 然后您必须引入可以为每个方法共享和测试的私有函数。

        private int Sum(int a, int b)
        {
            return a+b;
        }
        
        int ISample.Sum(int a,int b)
        {
            return Sum(a,b);
        }
        
        int ISample.Multiplication(int x,int a,int b)
        {
           return x*Sum(a,b);
        }
        

        【讨论】:

          【解决方案6】:

          我用过的唯一可能完成您所说的工具是Moles。如果您使用的是起订量,则无法做到这一点。但是,无论哪种方式,我都建议将您的班级作为一个单元进行测试。也就是说,如果您已经为 Sum() 编写了测试并且对其行为感到满意,请继续为 Multipication() 编写测试,如果它们暴露了问题,则根据需要在 Sum() 或 Multiplication 中修复它们。

          【讨论】:

            猜你喜欢
            • 2020-06-06
            • 2017-01-08
            • 1970-01-01
            • 2014-06-24
            • 2021-12-13
            • 1970-01-01
            • 1970-01-01
            • 2017-10-13
            • 2016-11-12
            相关资源
            最近更新 更多