模拟 OpenXML SDK SpreadsheetDocument

Mocking OpenXML SDK SpreadsheetDocument

我想使用此处描述的流程:Automated Testing OpenXML SDK (这里也有触及:Unit testing an application that talks to microsoft word via OpenXML

然而,怎样才能嘲笑这样的东西呢? 我做了如下界面:

public interface IExcelDocument
{
    Row GetRow(uint rowIndex, SheetData sheetData);
    SharedStringTablePart GetSharedStringTablePart(SpreadsheetDocument excelDoc);
    WorksheetPart GetWorksheetPart(SpreadsheetDocument excelDoc, string sheetName);
    Cell InsertCellInWorksheet(string columnName, uint rowIndex, WorksheetPart worksheetPart);
    Row InsertRow(WorksheetPart worksheetPart);
    int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart);
}

我想模拟会是这样的:

[TestMethod()]
public void Excel_GetWorkseetPartTest()
{
    Mock<IExcelDocument> mockExcelDocument = new Mock<IExcelDocument>();
    string sheetName = "sheet";
    var excelMock = mockExcelDocument.Object.GetWorksheetPart(MySpreadsheetDocument, sheetName);

    Assert.IsTrue(excelMock != null);
}

GetWorksheetPart 方法,我想对其进行单元测试并驻留在实现接口 IExcelDocument 的 class 中,如下所示:

public WorksheetPart GetWorksheetPart(SpreadsheetDocument excelDoc, string sheetName)
{
    Sheet sheet = excelDoc.WorkbookPart.Workbook.Descendants<Sheet>()
        .SingleOrDefault(s => s.Name == sheetName);
    if (sheet == null)
    {
        throw new ArgumentException(
            String.Format("No sheet named {0} found in spreadsheet {1}",
                sheetName, _filePath), "sheetName");
    }
    return (WorksheetPart)excelDoc.WorkbookPart.GetPartById(sheet.Id);
}

我无法绕过 MySpreadsheetDocument,因为我还需要实施 SpreadsheetDocument.Open 方法,但不确定这是否合理。

我是这样称呼GetWorksheetPart的:

using (SpreadsheetDocument _excelDoc = SpreadsheetDocument.Open(_filePath, true))
{
    IExcelDocument excelDoc = new ExcelDocument();
    WorksheetPart worksheetPart = excelDoc.GetWorksheetPart(_excelDoc, sheetName);
}

您混淆了为单元测试抽象依赖项的概念。

举个例子class

public class ExcelDocument {

    public WorksheetPart GetWorksheetPart(SpreadsheetDocument excelDoc, string sheetName)
    {
        Sheet sheet = excelDoc.WorkbookPart.Workbook.Descendants<Sheet>()
            .SingleOrDefault(s => s.Name == sheetName);
        if (sheet == null)
        {
            throw new ArgumentException(
                String.Format("No sheet named {0} found in spreadsheet {1}",
                    sheetName, _filePath), "sheetName");
        }
        return (WorksheetPart)excelDoc.WorkbookPart.GetPartById(sheet.Id);
    }
}

此方法依赖于外部组件SpreadsheetDocument

SpreadsheetDocument就是这种情况下需要抽象的东西。

查看被测方法,该方法需要能够获得 Sheet,因此您的抽象必须提供该功能。它还需要能够获得 WorksheetPart

由此可以导出如下接口

public ISpreadsheetDocument {    
    Sheet GetSheet(string name);
    WorksheetPart GetPartById(string id);
}

这会将被测方法更改为此

public WorksheetPart GetWorksheetPart(ISpreadsheetDocument excelDoc, string sheetName)
{
    Sheet sheet = excelDoc.GetSheet(sheetName);
    if (sheet == null)
    {
        throw new ArgumentException(
            String.Format("No sheet named {0} found in spreadsheet {1}",
                sheetName, _filePath), "sheetName");
    }
    return excelDoc.GetPartById(sheet.Id);
}

如果单元测试需要,您现在可以 mock/fack excelDoc,然后您的生产实施将包装外部功能。

public class SpreadsheetDocumentWrapper : ISpreadsheetDocument {
    private SpreadsheetDocument excelDoc;
    public SpreadsheetDocumentWrapper(SpreadsheetDocument excelDoc) {
        this.excelDock = excelDock;
    }

    public Sheet GetSheet(string name) {
        return excelDoc.WorkbookPart.Workbook.Descendants<Sheet>()
            .SingleOrDefault(s => s.Name == sheetName);
    }

    public WorksheetPart GetPartById(string id) {
        return (WorksheetPart)excelDoc.WorkbookPart.GetPartById(id);
    }
}

所以您需要做的是查看您的 ExcelDocument class,确定其依赖项并将这些依赖项抽象为您可以模拟以进行单元测试的服务。