How do I refactor a code implementing 'using' key word , so that I can write unit tests for the method?

53 Views Asked by At

So, It seems I have arrived at an impasse. I have asked to write unit test for a legacy code base in .Net however I am frequently coming across code that is implementing the 'using' statement. This is problem because I am unable to mock the objects.

using (var package1 = new ExcelPackage(sourceHierarchyFile))               
{                     
     ExcelWorksheet worksheet = package1.Workbook.Worksheets[0];                     
     var result = _industryBAL.SaveSourceHierarchy(industryId, userEnterpriseId, worksheet);
}

I am using the FakeItEasy mocking framework. But there is no provision for this type of code. Plus Wrapper methods would be one of the options. Basically guys I really need your help since not implementing these is causing an issue in the Code Coverage percentage.

1

There are 1 best solutions below

4
Dan Csharpster On

I suggest a couple of options. Option 3 is what I recommend.

  • Option 1: Ideally, you would refactor the code for Dependency Injection, like @Blair Conrad was saying. Assuming you are using the EPPlus library, the ExcelPackage class is sealed and only inherits from System.Object and implements IDisposable, so extracting something like an IExcelPackage interface would not be easy.

  • Option 2: Apply a Simple Factory pattern and use a factory method there and inside the factory method you could add logic to decide if its debug then and then return a New ExcelPackage from a known test file.

    using (var package1 = ExcelPackageFactory.Create(sourceHierarchyFile))
    {
    ExcelWorksheet worksheet = package1.Workbook.Worksheets[0];
    var result = _industryBAL.SaveSourceHierarchy(industryId, userEnterpriseId, worksheet); }

However, refactoring so much legacy code is often not fun or efficient. So what I often do is instead write integration tests, often in NUnit or some UI testing system, that can run against a real higher level object, even if that is the website or console application, etc itself. Often I will have a set of tests that run against the dev site as a post-deployment step. Depending on how you run that, it may not give you credit in code coverage. Code coverage is not an ideal metric anyway. Branch coverage would be better, but it can be hard selling management on letting go of code coverage metrics.

  • Option 3: Add the ExcludeFromCodeCoverage attribute above this method. There is no business logic in the example you shared, so there isn't really much practical use it writing a worthless test just to get your code coverage up. It is only doing File IO.

    [ExcludeFromCodeCoverage] public void Foo() { // excel code here }