I am having issues unit testing classes that use EPPlus. In my mind, I have two options.
I can mock & inject the HttpPostedFileBase into a method, or I can mock & inject the EPPlus ExcelPackage class.
Mocking the HttpPostedFileBase, at least doing a true mock, seems limited. I can mock the basic properties on the file (MIME type, filename, etc), but to mock its InputStream in a way that allows the tests to actually interact with it, seems extremely difficult. The only solution I can come up with is to provide a real excel file, create a real FileStream with it, and assign that FileStream to my mock HttpPostedFileBase's InputStream. But then it's technically an integration test, not a unit test.
const string FakeFileName = "TestExcelFile.xlsx"; // path to an actual excel file
var fileStream = new FileStream(FilePath, FileMode.Open);
var fakeFile = A.Fake<HttpPostedFileBase>();
A.CallTo(() => fakeFile.InputStream).Returns(fileStream);
I figured if I wanted to do an actual unit test, I could mock and inject the EPPlus ExcelPackage class instead. I could then mock the related Worksheet, Columns & Cell classes, setting their properties dynamically to fit the conditions of my test, while never touching a real file. The problem is, most of the EPPlus classes are sealed, so I can't mock them with FakeItEasy. I tried creating wrapper classes for them (see below), so I could mock the wrapper class instead... but some of the classes I need to mock/wrap have internal constructors, so I can't instantiate them. (I did try getting around the internal constructor problem using a couple of ugly hacks, but didn't have success.) And so I've hit a wall with this option.
I am still a novice and have a lot to learn. Perhaps my concept of a wrapper class is incorrect, and I am doing it wrong. Is there a way around this I can't see, or should I just give up, use a real excel file, and call it an integration test? So far, that's what I am leaning towards.
public class ExcelWorksheetsWrapper : IEnumerable<ExcelWorksheet>
{
public readonly ExcelWorksheets _excelWorksheets;
public ExcelWorksheetsWrapper()
{
// internal constructor, can't instantiate
_excelWorksheets = new ExcelWorksheets();
}
public ExcelWorksheet Add(string worksheetName)
{
return _excelWorksheets.Add(worksheetName);
}
public IEnumerator<ExcelWorksheet> GetEnumerator()
{
return _excelWorksheets.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _excelWorksheets.GetEnumerator();
}
}
See Question&Answers more detail:
os