如何在被测试的类中调用方法?

Gag*_*der 9 c# refactoring nunit unit-testing rhino-mocks

我首先要说的是我对单元测试很新,我想开始使用TDD方法,但是现在我正在编写一些现有类的单元测试来验证它们在所有情况下的功能.

我已经能够使用NUnit和Rhino模拟测试我的大部分代码而没有太多麻烦.但是,我一直想知道单元测试函数最终会在同一个类中调用很多其他方法.我做不了类似的事情

classUnderTest.AssertWasCalled(cut => cut.SomeMethod(someArgs))
Run Code Online (Sandbox Code Playgroud)

因为被测试的课程不是假的.此外,如果我正在测试的方法调用被测试类中的其他方法,而这些方法又调用同一类中的方法,那么我将需要伪造大量值来测试"顶级"方法.由于我也是对所有这些"子方法"进行单元测试,我应该能够假设"SomeMethod"如果通过单元测试而无需担心这些低级方法的详细信息,则可以按预期工作.

以下是我一直在使用的一些示例代码,以帮助说明我的观点(我编写了一个类来管理使用NPOI导入/导出Excel文件):

    public DataSet ExportExcelDocToDataSet(bool headerRowProvided)
    {
        DataSet ds = new DataSet();

        for (int i = 0; i < currentWorkbook.NumberOfSheets; i++)
        {               
            ISheet tmpSheet = currentWorkbook.GetSheetAt(i);

            if (tmpSheet.PhysicalNumberOfRows == 0) { continue; }
            DataTable dt = GetDataTableFromExcelSheet(headerRowProvided, ds, tmpSheet);

            if (dt.Rows.Count > 0)
            {
                AddNonEmptyTableToDataSet(ds, dt);
            }
        }

        return ds;
    }

    public DataTable GetDataTableFromExcelSheet(bool headerRowProvided, DataSet ds, ISheet tmpSheet)
    {
        DataTable dt = new DataTable();
        for (int sheetRowIndex = 0; sheetRowIndex <= tmpSheet.LastRowNum; sheetRowIndex++)
        {
            DataRow dataRow = GetDataRowFromExcelRow(dt, tmpSheet, headerRowProvided, sheetRowIndex);
            if (dataRow != null && dataRow.ItemArray.Count<object>(obj => obj != DBNull.Value) > 0)
            {
                dt.Rows.Add(dataRow);
            }
        }

        return dt;
    }

...
Run Code Online (Sandbox Code Playgroud)

您可以看到ExportExcelDocToDataSet(在本例中是我的"顶级"方法)调用GetDataTableFromExcelSheet,它调用GetDataRowFromExcelRow,它调用在同一个类中定义的其他几个方法.

那么,为了使其更加单元可测试而不必使用子方法调用的存根值,建议的重构此代码的策略是什么?有没有办法在被测试的类中伪造方法调用?

在此先感谢您的任何帮助或建议!

The*_*rff 6

修改测试对象(SUT).如果某些东西难以进行单元测试,那么设计可能会很尴尬.

在被测试的类中进行伪造方法调用会导致超过指定的测试.结果是非常脆弱的测试:只要你修改或重构类,那么你很可能还需要修改单元测试.这导致单元测试的维护成本过高.

为了避免过度指定的测试,请专注于公共方法.如果此方法调用类中的其他方法,请不要测试这些调用.另一方面:应测试对其他依赖组件(DOC)的方法调用.

如果你坚持这一点并且感觉你在测试中错过了一些重要的东西,那么它可能是一个类或方法做得太多的标志.如果是班级:寻找违反单一责任原则(SRP)的行为.从中提取类并单独测试它们.在方法的情况下:在几个公共方法中将方法拆分并分别测试每个方法.如果这仍然太尴尬,你肯定有一个违反SRP的类.

在特定情况下,你可以执行以下操作:提取方法ExportExcelDocToDataSet,并GetDataTableFromExcelSheet分为两个不同类别(也许叫他们ExcelToDataSetExporterExcelSheetToDataTableExporter).包含这两种方法的原始类应该引用这两个类并调用之前提取的那些方法.现在,您可以单独测试所有三个类.应用Extract Class重构(book)来实现原始类的修改.

另请注意,编写和维护时,改装测试总是有点麻烦.原因是没有进行单元测试而编写的SUT往往设计笨拙,因此难以测试.这意味着单元测试的问题必须通过修改SUT来解决,并且不能通过拉伸单元测试来解决.