代码之家  ›  专栏  ›  技术社区  ›  anonymous

TDD:编写可测试类的帮助

  •  6
  • anonymous  · 技术社区  · 16 年前

    应用程序背景:

    我有一个作为字符串读入的采购订单的文本转储。我需要解析文本并返回新采购订单号、新行项目号、旧采购订单号、旧采购订单行号。很简单。

    目前,我只处理新的采购订单详细信息(编号/行),并且有如下模型:

    public class PurchaseOrder
    {
        public string NewNumber {get; private set;}
        public string NewLine {get; private set;}
    
        new public PurchaseOrder(string purchaseOrderText)
        {
            NewNumber = GetNewNumber(purchaseOrderText);
            NewLine = GetNewLine(purchaseOrderText);
        }
    
        // ... definition of GetNewNumber / GetNewLine ...
        //  both return null if they can't parse the text
    }
    

    public void Purchase_Order_Is_Valid_When_New_Purchase_Order_Number_And_Line_Number_Are_Not_Null()
    {
        PurchaseOrder order = new PurchaseOrder()
        {
            NewNumber = "123456",
            NewLine = "001"
        };
    
        Assert.IsTrue(order.IsValid);
    }
    

    这很容易,但允许公共设置器和无参数构造函数似乎是一个糟糕的折衷方案。因此,另一种方法是在构造函数中输入一个“purchaseOrderText”值,但随后我还要测试“GetNewNumber”和“GetNewLine”的代码。

    我有点困惑于如何将其作为一个可测试类编写,同时试图将其锁定在对模型有意义的方面。这似乎是一个常见的问题,所以我想我只是缺少了一个明显的概念。

    5 回复  |  直到 16 年前
        1
  •  8
  •   orip    16 年前

    public class PurchaseOrder
    {
        public PurchaseOrder(string newNumber, string newLine)
        {
            NewNumber = newNumber;
            NewLine = newLine;
        }
        // ...
    }
    

    那么测试就很容易,而且是孤立的-你不是在测试 GetNewNumber GetNewLine 同时

    帮助使用 PurchaseOrder 您可以创建一个工厂方法,将其组合在一起:

    public static PurchaseOrder CreatePurchaseOrder(string purchaseOrderText)
    {
       return new PurchaseOrder(
         GetNewNumber(purchaseOrderText),
         GetNewLine(purchaseOrderText));
    }
    
        2
  •  2
  •   Rob Prouse    16 年前

    不要将setter公开,而是将它们内部化,然后在主项目中使测试程序集内部可见。这样,您的测试可以看到您的内部成员,但其他人无法看到。

    在你的主要项目中,放一些像这样的东西;

    [assembly: InternalsVisibleTo( "UnitTests" )]
    

    其中UnitTests是测试程序集的名称。

        3
  •  1
  •   tvanfosson    16 年前

    在测试项目中为类创建私有访问器,然后使用该访问器设置测试的属性。在VS中,您可以通过在类中单击鼠标右键,选择“创建专用访问器”,然后选择测试项目来创建专用访问器。在测试中,您可以这样使用它:

    public void NameOfTest()
    {
        PurchaseOrder_Accessor order = new PurchaseOrder_Accessor();
        order.NewNumber = "123456";
        order.NewLine = "001";
        Assert.IsTrue(order.IsValid);
    }
    

    如果您有默认构造函数,则可以执行以下操作:

    public void NameOfTest()
    {
        PurchaseOrder order = new PurchaseOrder()
        PurchaseOrder_Accessor accessor =
                    new PurchaseOrder_Accessor( new PrivateObject(order) );
        accessor.NewNumber = "123456";
        accessor.NewLine = "001";
        Assert.IsTrue(order.IsValid);
    }
    
        4
  •  0
  •   trendl    16 年前

    我可能会创建一个新的构造函数PublicPurchaseOrder(stringNewNumber,stringNewLine)。依我看,无论如何你都可能需要它。

        5
  •  0
  •   cordellcp3    16 年前

    有点离题:)

    使用TDD,首先要编写单元测试,然后编写足够的代码通过测试,然后再进行重构。通过首先编写测试,您应该确切地知道如何编程以使代码可测试!

    只要我的2美分。。。