2016-04-14 152 views
1

我有一個方法(下),從MVC應用程序,然後輸出一個Excel文件中的控制器調用。如何正確測試此方法?

方法:

public static void ExportToExcel(IEnumerable<dynamic> data, string bookName, string sheetName) 
{ 
    XLWorkbook workbook = new XLWorkbook(); 
    var worksheet = workbook.Worksheets.Add(sheetName); 
    worksheet.Cell(1, 1).InsertTable(data); 

    HttpContext.Current.Response.Clear(); 
    HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
    HttpContext.Current.Response.AddHeader("content-disposition", String.Format(@"attachment;filename={0}.xlsx", bookName.Replace(" ", "_"))); 

    using (MemoryStream memStream = new MemoryStream()) 
    { 
     workbook.SaveAs(memStream); 
     memStream.WriteTo(HttpContext.Current.Response.OutputStream); 
     memStream.Close(); 
    } 
    HttpContext.Current.Response.End(); 
} 

控制器:

[ActionName("ExportData")] 
public ActionResult ExportData() 
{ 
    ExcelExport.ExportToExcel(_dbaccess.GetAllData()), "Workbook", "Worksheet"); 

    return RedirectToAction("Index"); 
} 

我如何測試這個方法?

+1

這個方法與'HttpContext'緊密相連。這使得測試有點困難,但並非不可能。您想要測試哪種方法。 'ExportToExcel'或'ExportData'。你在使用什麼測試框架? – Nkosi

+0

理想情況下,但最重要的將是'ExportData' – haddow64

+1

你說測試正確(基於意見)你想要準確測試什麼。我有一個想法,但這些都是你在進入測試過程之前需要陳述/瞭解的東西。 – Nkosi

回答

1

首先,您需要重構該方法,使其更容易測試。這裏混雜着太多的關注點,使測試變得簡單。 (我的想法)。

帶出工作簿的一代,可以屬於同一類或一些依賴

public interface IGetWorkBook { 
    XLWorkbook GetWorkBook(IEnumerable<dynamic> data, string sheetName); 
} 

其實現可以像你在你原來的方法是什麼。

public XLWorkbook GetWorkBook(IEnumerable<dynamic> data, string sheetName) {  
    XLWorkbook workbook = new XLWorkbook(); 
    var worksheet = workbook.Worksheets.Add(sheetName); 
    worksheet.Cell(1, 1).InsertTable(data);  
} 

接下來你需要抽象掉緊耦合到HttpContext

也有一些好文章大約避過測試與HttpContext

Don't mock HttpContext他不喜歡被人嘲笑! :)

您要問的問題是what am I trying to achieve?。在這種情況下,我們希望將工作簿保存爲某些內容。是的,在這種情況下,它的響應是HttpContext,但它可能是別的。爲此,我們需要一個抽象

public interface IWriteWorkbook { 
    void Write(XLWorkbook workbook, string bookName); 
} 

,你可以稍後包括在派生類中的HttpContext你這麼愛用。

void Write(XLWorkbook workbook, string bookName) { 
    HttpContext.Current.Response.Clear(); 
    HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
    HttpContext.Current.Response.AddHeader("content-disposition", String.Format(@"attachment;filename={0}.xlsx", bookName.Replace(" ", "_"))); 

    using (MemoryStream memStream = new MemoryStream()) 
    { 
     workbook.SaveAs(memStream); 
     memStream.WriteTo(HttpContext.Current.Response.OutputStream); 
     memStream.Close(); 
    } 
    HttpContext.Current.Response.End(); 
} 

這也可以改善,但這是這篇文章的一面。

重構後的方法在所有更改後都可能看起來像這樣。

public interface IExcelExporter { 
    void ExportToExcel(IEnumerable<dynamic> data, string bookName, string sheetName); 
} 

public class ExcelExport : IExcelExporter { 
    IGetWorkBook workbookgGetter; 
    IWriteWorkbook workbookWriter; 

    public ExcelExport (IGetWorkBook workbookgGetter,IWriteWorkbook workbookWriter) { 
     this.workbookgGetter = workbookgGetter; 
     this.workbookWriter = workbookWriter; 
    } 

    public void ExportToExcel(IEnumerable<dynamic> data, string bookName, string sheetName) 
    { 
     XLWorkbook workbook = workbookgGetter.GetWorkBook(data, sheetName); 
     void workbookWriter.Write(workbook,bookName);   
    }  
} 

好吧,呃...這是很多。沒想到你會這麼做?但最終它是值得的。我認爲? :)

現在我們需要瞄準控制器。

public class MyExcelController: Controller { 

    public MyExcelController(IExcelExporter exporter){ 
     ExcelExport = exporter; 
    } 

    IExcelExporter ExcelExport{get; private set;} 

    [ActionName("ExportData")] 
    public ActionResult ExportData() 
    { 
     ExcelExport.ExportToExcel(_dbaccess.GetAllData(), "Workbook", "Worksheet"); 

     return RedirectToAction("Index"); 
    } 
} 

請注意,如果原來的控制器動作沒有改變,而它周圍的一切都有:)甜!

現在我們準備模擬和測試我們的心中的內容。

您可以測試IGetWorkBook.GetWorkBook

您可以測試IWriteWorkbook.Write

您可以測試ExcelExport.ExportToExcel

,以確保他們都按預期運行。

+0

哇,這是一些迴應,非常感謝。非常有用。 – haddow64

2

您可能應該更多地分解該方法。創建一個返回生成的字節數組,表示該文件一個byte []的方法:

public static byte[] ExportToExcel(IEnumerable<dynamic> data, string bookName, string sheetName) 

,然後創建實際保存到磁盤的方法:

public static bool SaveFileToDisk(byte[] file, string path) 

然後,您可以測試ExportToExcel方法斷言它返回一個已知字節[]