Need to run unit tests on a custom class that is heavely dependant on Office.Interop (COM) classes

◇◆丶佛笑我妖孽 提交于 2019-12-11 06:29:38

问题


I have a class called ExcelManager that is responsible for taking a path to an excel file in its constructor and has a method that takes a Sheet Name as a string or Sheet Index as an int, it then parses the data on that sheet minus headers and builds and returns a DataTable.

I have written integration tests that successfully test most of the ExcelManager class however they can only run on a system that has Excel installed.

What I am looking to do is either break down the ExcelManager class so that I can mock a spreadsheet and test without the need for Excel or find a way to unit test and possible inject mocked object for testing purposes (i'm not sure which is better practice) but I can't really see a way to do this, here is some of the Excel Manager code:

public ExcelManager(string FilePath)
    {
        try
        {
            application = new ApplicationClass();
        }
        catch (Exception)
        {
            throw new Exception("This feature requires a version of Microsoft Excel developed in 2002 or later, which is not detected on your computer.");
        }

        application.Visible = false;
        application.ScreenUpdating = false;
        application.DisplayAlerts = false;
        this.FilePath = FilePath;

        workbook = application.Workbooks.Open(FilePath, false, false, miss, miss, miss, miss, miss, miss, miss, miss, miss, miss, miss, miss);

    }

This is the method that opens the specified sheet and builds a DataTable The headerRng lines are used to limit the selection to user entered data, there are some constant fields in the spreadsheet that need not be read in.

public DataTable GetRangeValue(int SheetIndex)
{
    worksheet = (Worksheet)workbook.Sheets[SheetIndex];

    var headerRng = worksheet.get_Range("A1", miss);
    headerRng = headerRng.get_End(XlDirection.xlToRight);
    headerRng = worksheet.get_Range("A1", headerRng);
    var headerData = (object[,])headerRng.Value2;
    var columnCount = headerData.GetLength(1);

    var last = worksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);

    var dataRng = worksheet.get_Range("A2", last);

    var sheetData = (object[,])dataRng.Value2; // the rest of the code is the DataTable processing

There is another method that takes the string name for the sheet and calls this one with the sheet index.


回答1:


Your best bet would be pass the application object into the constructor of your ExcelManager class.

This would allow you to use a mocking framework to create a fake version of excel passing it into your class in your unit tests.

The downside is that the mock object's setup ends up knowing alot about the internal behaviour of your Manager class which is really behavioural testing rather than black box testing and can be a pain when refactoring (a kind of fragile tests code smell)

Not ideal but com-interop stuff a bit of a weak area when it comes to unit testing I've found.

There is an interesting article demonstrating such an approach here



来源:https://stackoverflow.com/questions/5544446/need-to-run-unit-tests-on-a-custom-class-that-is-heavely-dependant-on-office-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!