OpenXML的嘲讽与起订量 [英] Mocking OpenXML with Moq

查看:195
本文介绍了OpenXML的嘲讽与起订量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我应该如何测试以下 GetWorksheetPart 方法:

 公开类ExcelDocument:IExcelDocument 
{
私人只读字符串_filePath;

公共ExcelDocument(字符串文件路径)
{
_filePath =文件路径;
}

公共WorksheetPart GetWorksheetPart(ISpreadsheetDocument excelDoc,串SHEETNAME)
{
表表= excelDoc.GetSheet(SHEETNAME);
如果(表== NULL)
{
抛出新的ArgumentException(
的String.Format(无纸名为{0}在电子表格中{1},
SHEETNAME,_filePath),SHEETNAME);
}
返回excelDoc.GetPartById(sheet.Id);
}
}



其中, IExcelDocument 和包装的 SpreadsheetDocumentWrapper 接口包括:

 公共接口IExcelDocument 
{
WorksheetPart GetWorksheetPart(ISpreadsheetDocument excelDoc,串SHEETNAME);
}

公共接口ISpreadsheetDocument
{
表GetSheet(字符串名称);

WorksheetPart GetPartById(字符串ID);
}

下面是包装本身。

 公共类SpreadsheetDocumentWrapper:ISpreadsheetDocument 
{
私人SpreadsheetDocument excelDoc;

公共SpreadsheetDocumentWrapper(SpreadsheetDocument excelDoc)
{
this.excelDoc = excelDoc;
}

公共表GetSheet(字符串SHEETNAME)
{
返回excelDoc.WorkbookPart.Workbook.Descendants<板>()
.SingleOrDefault(S = GT; s.Name == SHEETNAME);
}

公共WorksheetPart GetPartById(字符串ID)
{
回报(WorksheetPart)excelDoc.WorkbookPart.GetPartById(ID);
}
}



最后,我试图执行的测试 GetWorksheetPart 。问题与此是,我不知道如何测试这个功能。想法是让一个 WorksheetPart 给出的表名和电子表格文档。

 公共类测试
{
[识别TestClass()]
公共类ExcelUpdateLogicTests
{
[TestMethod的()]
公共无效Excel_GetWorkseetPartTest()
{
&模拟LT; ISpreadsheetDocument> mockSpreadhseet =新的模拟< ISpreadsheetDocument>();
表表=新表();
串ID =1;
sheet.Name =表;
sheet.Id = ID;

mockSpreadhseet.Setup(DOC => doc.GetSheet(表))。返回(片);

mockSpreadhseet.Setup(DOC => doc.GetPartById(ID))。返回(????);

&模拟LT; IExcelDocument> mockExcelDocument =新的模拟< IExcelDocument>();
WorksheetPart mockWorkseet = mockExcelDocument.Object
.GetWorksheetPart(mockSpreadhseet.Object,表);

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

下面是一般的OpenXML结构树电子表格:




  | 
WorkbookPart
/ | \
工作簿WorkbookStylesPart WorksheetPart
| | |
表样式表的工作表
| / \
(指SheetData列
Worksheetparts)|



解决方案

由于 ExcelDocument 是被测系统那么就没有必要嘲笑 IExcelDocument 。你应该嘲笑/存根/假测试SUT需要依赖



现在我能得到你的测试通过这样的...

 公共类的测试{
[识别TestClass()]
公共类ExcelUpdateLogicTests {
[TestMethod的()]
公共无效Given_SheetName_ExcelDocument_Should_GetWorkseetPart(){
//安排
变种流=新的MemoryStream(); //避免使用磁盘上的
VAR spreadsheetDocument = SpreadsheetDocument.Create实际的文件(流SpreadsheetDocumentType.Workbook);

//添加WorkbookPart。
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook =新的工作簿();

//添加WorksheetPart。
WorksheetPart worksheetPart = workbookpart.AddNewPart< WorksheetPart>();
worksheetPart.Worksheet =新的工作表(新SheetData());

//添加表列表。
表表= spreadsheetDocument.WorkbookPart.Workbook.AppendChild<表及GT;(新表());

//追加新的工作表,并将其与该工作簿关联。
串expectedId = workbookpart.GetIdOfPart(worksheetPart);
串SHEETNAME =MySheet的工作;

表表=新表(){
n = expectedId,
SheetId = 1,
名称= SHEETNAME
};
sheets.Append(片);

VAR包装=新SpreadsheetDocumentWrapper(spreadsheetDocument);

串fakeFilePath =路径;
变种SUT =新ExcelDocument(fakeFilePath);

//法案
WorksheetPart结果= sut.GetWorksheetPart(包装,SHEETNAME);

//断言
Assert.IsNotNull(结果);
VAR actualId = workbookpart.GetIdOfPart(结果);
Assert.AreEqual(expectedId,actualId);
}
}
}



因此,无论做的过程提出了当前设计的一些问题。



如果创建抽象的整点是要隐藏实现细节,并减少对外部框架的紧密结合,使事情变得更容易嘲笑,然后测试不必创建实际 SpreadsheetDocument 和包装它的测试似乎是多余的。



很多框架的部分都难以给出嘲笑其内部产生。我会躲在其他抽象落后,但因为我不知道有足够的了解该系统的最终目标,我不能劝,以你应该采取什么样的设计结构。


How should I test the following GetWorksheetPart method:

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

Where IExcelDocument and wrapper's SpreadsheetDocumentWrapper interfaces are:

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

public interface ISpreadsheetDocument
{
    Sheet GetSheet(string name);

    WorksheetPart GetPartById(string id);
}

Here is the wrapper itself.

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

Finally, the test which I tried to implement for GetWorksheetPart. Issue with this is that I am not sure how to test this functionality. Idea is to get a WorksheetPart given the sheet name and the spreadsheet document.

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

Here is the general OpenXML structure tree for Spreadsheets:

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

解决方案

Since ExcelDocument is the system under test then there is no need to mock IExcelDocument. You should mock/stub/fake the dependencies needed to test the SUT

Now I was able to get your test to pass like this...

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

The process of doing so however raised some questions about the current design.

If the whole point of creating the abstraction was to hide the implementation details and reduce the tight coupling on the external framework to make things easier to mock and test then having to create an actual SpreadsheetDocument and wrapping it for the test seems redundant.

A lot of the parts of the framework are difficult to mock given their internal generation. I would hide those behind other abstractions, but given that I do not know enough about the end goal of this system I cannot advise as to what design structure you should be taking.

这篇关于OpenXML的嘲讽与起订量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆