如何使课程更可测试?

时间:2013-04-10 08:04:41

标签: c# .net oop unit-testing encapsulation

我有这个:

 class FooGenerator:IFooGenerator {
      private object _generated;

      public void Generate() {
         // Generating
         GenerateSmallPart();
         GenerateOtherSmallPart();
         GenerateTinyPart();
         // A lot similar
      }

      private void GenerateSmallPart() {
         //add small part to _generated
      }

      private void GenerateOtherSmallPart() {
         //add small part to _generated
      }

      private void GenerateTinyPart() {
         //add small part to _generated
      }
   }

   internal interface IFooGenerator {
      void Generate();
   }

在我的应用程序中,我只通过IoC使用IFooGenerator,但我想测试所有这些子方法。

正如我发现here,一个选项是使用所有子方法提取类。但为什么我需要这样做。它仅用于FooGenerator

您有什么建议我如何让我的课程更可测试?

3 个答案:

答案 0 :(得分:2)

我将与您分享我通常如何处理这种情况。如果我看到我想出于某种原因测试一些私有方法(比如很难将输入参数存根来测试所有代码流) - 这通常意味着我的类的复杂性很高,我需要重构我的代码。在你的情况下(我不知道你的方法在做什么)你可以使用类似的东西:

interface IPartGenerator
{
   void GeneratePart();
}

class SmallPartGenerator : IPartGenerator
{
   void GeneratePart();
}

class OtherSmallPartGenerator : IPartGenerator
{
   void GeneratePart();
}

class TinyPartGenerator : IPartGenerator
{
   void GeneratePart();
}

class FooGenerator:IFooGenerator 
{
   private IPartGenerator[] partGenerators = new IPartGenerator[] 
                        {
                           new SmallPartGenerator(), 
                           new OtherSmallPartGenerator(), 
                           new TinyPartGenerator ()
                        }

   public void Generate()
   {
        foreach (var partGenerator in partGenerators)
        {
              partGenerator.GeneratePart();
        }
   }
}

现在您可以分别测试每个零件生成器。

答案 1 :(得分:1)

谁是客户?

许多人(Roy OsheroveMichael Feathers)认为测试客户端与接口或服务客户端一样有效。

考虑到这一点,我认为通过公开一些私有方法来打开可测试的接缝可能会略微违背封装原则。

答案 2 :(得分:0)

你的课不是一件事,而是几件事 - 每一件都封装在私人方法中。这违反了单一责任原则(SRP)。根据SRP,一个班级应该只做一件事。

Neil Thompson建议您将私有方法公之于众。这至少使它们可以进行单元测试,但它们仍然是SRP违规。如果你的班级有很多不同的东西,那么启蒙往往很复杂;你必须在满足所有方法需求的状态下创建类,尽管你只想测试一个小角落。这对可测试性没有任何好处。

在此之后,outcoldman的回答是一个更健全的设计。他的代码没有违反SRP。