【问题标题】:What is the simplest unit test to implement for asserting a particular method is called?为断言特定方法而实现的最简单的单元测试是什么?
【发布时间】:2011-09-02 13:27:59
【问题描述】:

我有一个类,我想在其公共方法之一中实现单元测试,以测试是否调用了特定方法。

为简化起见,让我们拿下面的类和单元测试。

我应该更改或实现什么(如接口等),以便我可以断言“MakeNoise 方法调用 Bark 方法”

如果需要,我可以使用 RhinoMocks。

public class Animal
{
    public string AnimalType {get; set;}
    public string Bark()
    {
        if(AnimalType=="dog")
        {
            return "Hof! Hof! Hof!";
        }

        return string.Empty;
    }

    public string MakeNoise()
    {
        if(AnimalType=="dog")
        {
            return Bark();
        }

        return 
            string.Empty;

    }
}

[TestMethod]
public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
{

    var dog = new Animal(){AnimalType="dog"};
    dog.MakeNoise();

    // How can I test if the MakeNoise method called BarkMethod ?

}

【问题讨论】:

  • pencilCake,在你的 Bark() 中你总是返回 string.Empty 本身,那么你如何测试一个有效的呢?
  • 这段代码是半真实的吗?典型示例通常是从 Animal 继承并覆盖 MakeNoise 方法的 Dog。这完全颠覆了你的问题。然后你对Dog 进行单元测试以确保它具有正确的行为。
  • 我们先说说为什么你的Animal类有Bark方法。
  • 重要的是行为,而不是调用了某个方法。

标签: c# .net unit-testing rhino-mocks


【解决方案1】:

这是你感兴趣的,输出。测试输出。

var expected = "Hof! Hof! Hof!";
var actual = dog.MakeNoise();
Assert.AreEqual(actual, expected);

如果该方法在被测类内部,则它是一个实现细节。您可能想要测试交互的地方是您的班级是否有合作者,并且您希望将Animal 的测试与合作者隔离(可能是Bar)。 然后您可能会选择使用假冒的Bar 以确保Animal 正确运行(当然,您需要针对真实进行适当的测试>Bar)。如果这更接近您的真实问题,请更新它。

话虽如此,您的类层次结构(如果这确实是一个指示)可能需要一些工作。 Animal 不应该有只与狗相关的方法。你不应该在课堂上进行类型检查(类、枚举等)。创建一个继承自AnimalDog,让它适当地覆盖MakeNoise 方法。

class Animal
{
    public virtual string MakeNoise() { return whatever; }
}

class Dog : Animal 
{
    public override string MakeNoise() { return "Hof! Hof! Hof!"; }
}

//
Animal dog = new Dog();
var noise = dog.MakeNoise();

您甚至可以将Animal 抽象化。

【讨论】:

    【解决方案2】:

    你永远不应该检查某个方法是否调用了另一个方法。实际的实现不应该是有趣的。

    恕我直言,正确的单元测试应该是“黑盒”测试。你不应该知道一个方法包含什么样的逻辑。您应该只知道它提供的那种结果以及它可以抛出什么样的异常(以及在什么条件下)。而那些指定的案例是你应该测试的。

    【讨论】:

      【解决方案3】:

      虽然我同意@jgauffin 的观点,但单元测试实际上不应该那样做,但无论如何都有一种 dirty 方法可以做到这一点。

      首先,定义你的 Bark 方法virtual。然后,在作为测试套件一部分的继承类中覆盖它。

      public class AnimalTestClass : Animal
      {
           public bool BarkCalled{get;set;}
      
           public override string Bark()
           {
                BarkCalled = true;
                return base.Bark();
           }
      }
      

      然后,在你的测试方法中,实例化这个类

       [TestMethod]
       public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
       {
      
           var dog = new AnimalTestClass(){AnimalType="dog"};
           dog.MakeNoise();
      
           // How can I test if the MakeNoise method called BarkMethod ?
           Assert.IsTrue(dog.BarkCalled);
       }
      

      编辑:修正了代码拼写错误(忘记调用 base.Bark())

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 2015-04-07
        • 1970-01-01
        • 1970-01-01
        • 2018-02-09
        • 1970-01-01
        • 1970-01-01
        • 2012-01-08
        • 2021-11-04
        相关资源
        最近更新 更多