Reputation: 2626
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
Upvotes: 1
Views: 1494
Reputation: 247323
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.
Upvotes: 2