将 TDD 与 OpenXml-SDK 结合使用

发布于 2024-09-26 18:24:19 字数 2854 浏览 6 评论 0原文

我已经开始使用 TDD 方法来开发一个从 Excel 文件读取数据的小型应用程序。使用存储库模式类型方法,我遇到了一个令我困惑的障碍。

为了读取 Excel 文件,我使用 OpenXml-SDK。现在,通常使用 SDK 读取 Excel 文件需要几个甚至更多的步骤才能真正获取您想要读取的值。

到目前为止我所采取的方法反映在以下测试和随附的功能中。

    [Test]
    public void GetRateData_ShouldReturn_SpreadSheetDocument()
    {
        //Arrange
        var fpBuilder = new Mock<IDirectoryBuilder>();
        fpBuilder.Setup(fp => fp.FullPath()).Returns(It.IsAny<string>());

        var doc = new Mock<IOpenXmlUtilities>();
        doc.Setup(d => d.OpenReadOnlySpreadSheet(It.IsAny<string>()))
             .Returns(Mock.Of<SpreadsheetDocument>());

        swapData = new SwapRatesRepository(fpBuilder.Object, doc.Object);

        //Act
        var result = swapData.GetRateData();

        //Assert
        doc.Verify();
        fpBuilder.Verify();
    }

public class SwapRatesRepository: IRatesRepository<SwapRates>
{
    private const string SWAP_DATA_FILENAME = "DATE_MKT_ZAR_SWAPFRA1.xlsx";
    private IDirectoryBuilder builder;
    private IOpenXmlUtilities openUtils;

    public SwapRatesRepository(IDirectoryBuilder builder)
    {
        // TODO: Complete member initialization
        this.builder = builder;
    }

    public SwapRatesRepository(IDirectoryBuilder builder, 
                                       IOpenXmlUtilities openUtils)
    {
        // TODO: Complete member initialization
        this.builder = builder;
        this.openUtils = openUtils;
    }

    public SwapRates GetRateData()
    {
        // determine the path of the file based on the date
        builder.FileName = SWAP_DATA_FILENAME;
        var path = builder.FullPath();

        // open the excel file
        using(SpreadsheetDocument doc = openUtils.OpenReadOnlySpreadSheet(path))
        {
            //WorkbookPart wkBookPart = doc.WorkbookPart;
            //WorksheetPart wkSheetPart = wkBookPart.WorksheetParts.First();
            //SheetData sheetData = wkSheetPart.Worksheet
            //                                 .GetFirstChild<SheetData>();

        }

        return new SwapRates(); // ignore this class for now, design later 
    }
}

然而,打开电子表格后的下一步是实际开始询问 Excel 对象模型以检索值。如上所述,我对任何与开放 xml 相关的内容使用模拟。但是,在某些情况下,对象无法被模拟(或者我不知道如何模拟它们,因为它们是静态的)。这就产生了 IOpenXmlUtilities,它们只是对 OpenXml-SDK 的简单包装调用。

在设计方面,我们知道从 Excel 文件读取数据是一个短期解决方案(6-8 个月),因此这些测试暂时只影响存储库/数据访问。

显然,我不想放弃 TDD 方法(尽管它很诱人),所以我正在寻找有关如何使用 OpenXml SDK 继续我的 TDD 工作的建议和指导。另一方面与模拟有关 - 我对在这种情况下何时以及如何使用模拟感到困惑。我不想在不知不觉中编写测试 OpenXml-SDK 的测试。

*旁注:我知道我的设计的可靠性可以提高,但我现在先保留它。我有一组与 builder 对象相关的单独测试。可能发生的另一个副作用是 OpenXML-SDK 包装器库的设计。

编辑:当时不知道,通过为 OpenXML-SDK 创建 OpenXML-SDK 包装器,我使用了一种类似(或确切)的设计模式,称为 适配器模式

I have started using a TDD approach to develop a small app that reads data from Excel files. Using a repository pattern type approach I have come to a hurdle which baffles me.

In order to read the Excel files, I am using the OpenXml-SDK. Now typically reading from an Excel file using the SDK requires several if not more steps to actually get the values you want to read.

The approach I have taken thus far is reflected in the following test and accompanying function.

    [Test]
    public void GetRateData_ShouldReturn_SpreadSheetDocument()
    {
        //Arrange
        var fpBuilder = new Mock<IDirectoryBuilder>();
        fpBuilder.Setup(fp => fp.FullPath()).Returns(It.IsAny<string>());

        var doc = new Mock<IOpenXmlUtilities>();
        doc.Setup(d => d.OpenReadOnlySpreadSheet(It.IsAny<string>()))
             .Returns(Mock.Of<SpreadsheetDocument>());

        swapData = new SwapRatesRepository(fpBuilder.Object, doc.Object);

        //Act
        var result = swapData.GetRateData();

        //Assert
        doc.Verify();
        fpBuilder.Verify();
    }

public class SwapRatesRepository: IRatesRepository<SwapRates>
{
    private const string SWAP_DATA_FILENAME = "DATE_MKT_ZAR_SWAPFRA1.xlsx";
    private IDirectoryBuilder builder;
    private IOpenXmlUtilities openUtils;

    public SwapRatesRepository(IDirectoryBuilder builder)
    {
        // TODO: Complete member initialization
        this.builder = builder;
    }

    public SwapRatesRepository(IDirectoryBuilder builder, 
                                       IOpenXmlUtilities openUtils)
    {
        // TODO: Complete member initialization
        this.builder = builder;
        this.openUtils = openUtils;
    }

    public SwapRates GetRateData()
    {
        // determine the path of the file based on the date
        builder.FileName = SWAP_DATA_FILENAME;
        var path = builder.FullPath();

        // open the excel file
        using(SpreadsheetDocument doc = openUtils.OpenReadOnlySpreadSheet(path))
        {
            //WorkbookPart wkBookPart = doc.WorkbookPart;
            //WorksheetPart wkSheetPart = wkBookPart.WorksheetParts.First();
            //SheetData sheetData = wkSheetPart.Worksheet
            //                                 .GetFirstChild<SheetData>();

        }

        return new SwapRates(); // ignore this class for now, design later 
    }
}

However, the next steps after the spreadsheet is open would be to actually start interrogating the Excel object model to retrieve the values. As noted above, I making use of mocks for anything open xml related. However, in some cases the objects can't be mocked(or I don't know how to mock them since they are static). That gave rise to IOpenXmlUtilities which are merely simple wrapper calls into the OpenXml-SDK.

In terms of design, we know that reading data from excel files is a short term solution (6-8 months), so these tests only affect the repository/data access for the moment.

Obviously I don't want to leave the TDD approach(as tempting as it is), so I am looking for advise and guidance on how to continue my TDD endeavours with the OpenXml SDK. The other aspect relates to mocking - I am confused as to when and how to use mocks in this case. I don't want to unknowingly writes tests that test the OpenXml-SDK.

*Side note: I know that the SOLIDity of my design can be improved but I leaving that for now. I have a set of separate tests that relate to the builder object. The other side effect that may occur is the design of an OpenXML-SDK wrapper library.

Edit: Unbeknown at the time, by creating the OpenXML-SDK wrappers for the OpenXML-SDK, i have used a design pattern similar (or exact) called the Adaptor pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

未蓝澄海的烟 2024-10-03 18:24:19

如果您无法模拟它并且无法创建小型单元测试,那么最好将其提升到更高的水平并进行场景测试。您可以使用 [TestInitialize] 和 [TestCleanup] 方法来创建测试设置。

使用 Pex 和 Moles 可能是另一种测试方法。

If you can't mock it and can't create a small unittest, it might be better to take it to a higher level and make a scenario test. You can use the [TestInitialize] and [TestCleanup] methods to create a setup for the test.

using Pex and Moles might be another way to get it tested.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文