2015-05-06 24 views
2

好日子,單元測試MVC控制器使得靜態庫調用調用外部API

我感到困惑的單元測試如下:

1. MVC控制器:

[HttpGet] 
public async Task<PartialViewResult> DoExternalCallsAsync() 
{ 
    var model = new MyModel(); 

    await MyStaticLibrary.DoExternalWorkAsync(Server.MapPath("~\\") + "WorkSource.txt", model); 

    return PartialView("_MyResults", model); 
} 

2.靜態庫:

public static async Task DoExternalWorkAsync(string sourcePath, MyModel model) 
     { 
      var externalCalls = 
       System.IO.File.ReadAllLines(sourcePath) 
       .Where(line => (!string.IsNullOrEmpty(line) && line.First() != '#')) 
       .Select(p => DoExternalCall(p, model)); 

      await Task.WhenAll(externalCalls); 


     } 



private static async Task DoExternalCall(string urlPath, MyModel model) 
      { 
       var result = await GetExternalApiResultAysnc(urlPath); 

       // some code here... 



       return; 
      } 

基本上,控制器所做的就是調用一個外部API,它執行一些工作並返回結果或引發錯誤。

還有沒有接口或抽象類與外部Api。

我該如何去做單元測試呢? N. B.我無權改變外部Api的設計。

感謝,

回答

4

使用靜態類或代碼中的方法,使代碼很難進行適當的單元測試。見Is static universally 「evil」 for unit testing and if so why does resharper recommend it?,Static class/method/property in unit test, stop it or not,When to use static classes in C#

裹靜態API調用類爲實例類與接口:

public interface IMyLibrary 
{ 
    Task DoExternalWorkAsync(); 
} 

public class MyStaticLibrary : IMyLibrary 
{ 
    public async Task DoExternalWorkAsync(string sourcePath, MyModel model) 
    { 
     return await MyStaticLibrary.DoExternalWorkAsync(sourcePath, model); 
    } 
} 

然後你可以inject an instance into the controller's constructor

因爲這應該是單位在這個控制器的操作方法進行測試的唯一的事:

  • 是否代碼中調用使用適當的參數庫?
  • 該方法是否返回適當的對象?

在測試過程中,您可以在控制器中注入嘲笑IMyLibrary和驗證控制器正確調用模擬,你可以驗證結果是含不管它應該包含PartialViewResult

+0

謝謝你的回答。有一次我曾被告知你的設計只能用於你的主要目標。基本上,您不要將您的代碼調整爲「可測試」。靜態庫在那裏,因爲不需要它是靜態的。 另外,如何使用Server.Mappath控制器? – agfc

+1

那是一個廣泛的討論。我認爲你必須改變你的代碼以使其可測試,因爲這些利益是相互衝突的:最「密」或「最小」的代碼通常根本不可測試,而你想測試它。有許多模式可以幫助您使代碼更加可重用和可測試。我個人不喜歡靜態類,特別是當它們包含的方法有副作用時(在這種情況下,調用Web服務,這在測試期間不應該發生)。通常使用靜態類「所以我們不必使用'new'」,這不是使用靜態的藉口。 – CodeCaster

+0

至於'Server.MapPath()',請參見[單元測試Server.MapPath](http://stackoverflow.com/questions/19563106/unit-testing-for-server-mappath)。 – CodeCaster

0

該庫是執行某個工作單元的實施細節。它應該完全抽象出來。如果你想運行集成測試,那完全是一種不同的測試風格。