2013-04-10 28 views
6

我有这样的:如何让课程更具可测性?

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

在我的应用程序只能通过IFooGenerator国际奥委会使用,但我想测试所有的子方法。

当我发现here,一种选择是提取所有子方法的类。但为什么我需要这样做。它仅在FooGenerator中使用。

你有什么建议,我该如何让我的课更具可测试性?

+9

据我所知,你应该测试公共API,而不是内部,所以你应该测试'IFooGenerator.Generate'并检查结果是否你期望的。但是如果你真的想测试'构建'部分,那么将'Generate'部分提取到构建器中是个好主意......? – 2013-04-10 08:07:15

+0

由于所有这些方法都不会返回任何东西,我想知道你是怎么想测试它们的......你在使用Mocks吗?如果是这样,即使只是测试公共方法,也可以验证它们。但要小心:这很可能会造成脆弱的测试。 – 2013-04-10 08:07:16

+0

:)是啊!开始一些黑盒子/白盒测试flamewar :) 对我来说医生是对的。 – wonko79 2013-04-10 08:11:08

回答

1

谁是客户?

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

考虑到这一点,我认为可以通过公开某些私有方法来打开可测试的接缝,稍微违背封装原理就可以了。

+0

只需要补充一点,如果您可以在可测试性的名称中使用封装,那么我建议您在内部制作一些私有方法,并使用[InternalsVisibleTo attribute](http)向您的prod-assembly的朋友添加单元测试程序集://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx)。 – 2013-04-10 10:50:51

+0

@ aleksey.berezan这InternalsVisibleTo属性似乎对我来说是一种解决方法。我真的不想违背神圣的原则:) – 2013-04-10 11:22:12

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

现在你可以单独测试每个部分发电机。

0

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

尼尔汤普森建议你应该公开私人方法。这至少使得他们可以进行单元测试,但他们仍然是SRP违规。如果你的班级有许多不同的事情,那么启动往往很复杂;你必须创建一个满足所有方法需求的类,尽管你只想测试一个小角落。这对测试性没有任何好处。

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

+0

建议的方法建议相信我 - 我是一名医生违反SRP? – 2013-04-10 11:24:43

+0

在我的对话中,你的课堂仍然有许多不同的R(职责)和那种医生方法。 SRP意味着每个类只有一个R,所以是的,它违反了SRP。一旦你真正深入单元测试/ TDD,你会看到SRP的价值。 – Morten 2013-04-10 12:04:18

相关问题