2016-07-28 58 views
1

我應該如何測試以下GetWorksheetPart方法:嘲諷的OpenXML與起訂量

public class ExcelDocument : IExcelDocument 
{ 
    private readonly string _filePath; 

    public ExcelDocument(string filePath) 
    { 
     _filePath = filePath; 
    } 

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

IExcelDocument和包裝的SpreadsheetDocumentWrapper接口:

public interface IExcelDocument 
{ 
    WorksheetPart GetWorksheetPart(ISpreadsheetDocument excelDoc, string sheetName); 
} 

public interface ISpreadsheetDocument 
{ 
    Sheet GetSheet(string name); 

    WorksheetPart GetPartById(string id); 
} 

這裏是包裝本身。

public class SpreadsheetDocumentWrapper : ISpreadsheetDocument 
{ 
    private SpreadsheetDocument excelDoc; 

    public SpreadsheetDocumentWrapper(SpreadsheetDocument excelDoc) 
    { 
     this.excelDoc = excelDoc; 
    } 

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

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

最後,我試圖實施的測試爲GetWorksheetPart。與此問題是,我不知道如何測試此功能。想法是得到一個WorksheetPart給定工作表名稱和電子表格文檔。

public class Test 
{ 
    [TestClass()] 
    public class ExcelUpdateLogicTests 
    { 
     [TestMethod()] 
     public void Excel_GetWorkseetPartTest() 
     { 
      Mock<ISpreadsheetDocument> mockSpreadhseet = new Mock<ISpreadsheetDocument>(); 
      Sheet sheet = new Sheet(); 
      string id = "1"; 
      sheet.Name = "sheet"; 
      sheet.Id = id; 

      mockSpreadhseet.Setup(doc => doc.GetSheet("sheet")).Returns(sheet); 

      mockSpreadhseet.Setup(doc => doc.GetPartById(id)).Returns(????); 

      Mock<IExcelDocument> mockExcelDocument = new Mock<IExcelDocument>(); 
      WorksheetPart mockWorkseet = mockExcelDocument.Object 
       .GetWorksheetPart(mockSpreadhseet.Object, "sheet"); 

      Assert.IsTrue(mockWorkseet.GetIdOfPart(mockWorkseet) == id); 
     } 
    } 
} 

這裏是電子表格一般的OpenXML結構樹:

   Spreadsheet 
         |   
       WorkbookPart  
     /  |    \ 
    Workbook WorkbookStylesPart WorksheetPart 
     |   |    | 
    Sheets  StyleSheet  Worksheet 
     |      /  \  
    (refers to    SheetData  Columns 
    Worksheetparts)   | 
          Rows 

回答

1

由於ExcelDocument是被測系統那麼就沒有必要嘲笑IExcelDocument。你應該嘲笑測試SUT

現在我能得到你的測試通過這樣的需要/存根/假的依賴關係......

public class Test { 
    [TestClass()] 
    public class ExcelUpdateLogicTests { 
     [TestMethod()] 
     public void Given_SheetName_ExcelDocument_Should_GetWorkseetPart() { 
      //Arrange 
      var stream = new MemoryStream();//Avoid having to use actual file on disk 
      var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook); 

      // Add a WorkbookPart. 
      WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); 
      workbookpart.Workbook = new Workbook(); 

      // Add a WorksheetPart. 
      WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); 
      worksheetPart.Worksheet = new Worksheet(new SheetData()); 

      // Add a sheets list. 
      Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets()); 

      // Append the new worksheet and associate it with the workbook. 
      string expectedId = workbookpart.GetIdOfPart(worksheetPart); 
      string sheetName = "mySheet"; 

      Sheet sheet = new Sheet() { 
       Id = expectedId, 
       SheetId = 1, 
       Name = sheetName 
      }; 
      sheets.Append(sheet); 

      var wrapper = new SpreadsheetDocumentWrapper(spreadsheetDocument); 

      string fakeFilePath = "path"; 
      var sut = new ExcelDocument(fakeFilePath); 

      //Act 
      WorksheetPart result = sut.GetWorksheetPart(wrapper, sheetName); 

      //Assert 
      Assert.IsNotNull(result); 
      var actualId = workbookpart.GetIdOfPart(result); 
      Assert.AreEqual(expectedId, actualId); 
     } 
    } 
} 

這樣做的過程中卻提出了一些問題目前的設計。

如果創建抽象的目的是爲了隱藏實現細節並減少外部框架上的緊密耦合以使事情更容易模擬和測試,那麼必須創建實際的SpreadsheetDocument並將其包裝爲測試似乎是多餘的。

框架的很多部分都難以嘲笑他們的內部世代。我會隱藏那些隱藏在其他抽象背後的東西,但鑑於我對這個系統的最終目標不夠了解,我不能建議你應該採用什麼設計結構。

+0

感謝您的回答。我同意你對冗餘的評論。考慮到你的測試,看起來像'SpreadsheetDocumentWrapper'是多餘的,我可以直接在內存中加載的'ExcelDocument'對象上測試。 我使用'Moq'和'Verify'進行了測試。你可以看看,並給你的評論,爲什麼一個在另一個https://dotnetfiddle.net/hVHvlM? –

+1

我檢查了測試,它的工作原理。但是當測試通過並且您的驗證調用通過時,'mockWorksheet'是'null'。我的建議是試圖抽象出與更高級別的OpenXML部件的交互,並避免暴露似乎是實現細節的部分。 – Nkosi

+0

你說得對,'mockWorksheet'爲空。它僅驗證方法調用。當你說更高的水平時,你究竟是什麼意思。這是你已經展示過的東西,還是你想到的東西不同?如果這有幫助,應用程序的想法是將行插入到「.xlsx」文檔中,並且不涉及用戶界面,純後端。 –