2016-12-30 125 views
20

我有一個控制器中的函數,我是單元測試,希望在http請求頭中的值。我無法初始化HttpContext,因爲它是隻讀的。單元測試.NET核心MVC控制器的模擬HttpContext?

我的控制器功能預計,「設備ID」

[TestMethod] 
public void TestValuesController() 
{ 
    ValuesController controller = new ValuesController(); 

    //not valid controller.HttpContext is readonly 
    //controller.HttpContext = new DefaultHttpContext(); 

    var result = controller.Get(); 
    Assert.AreEqual(result.Count(), 2); 
} 

是否有直接的方式做到這一點,而無需使用第三方庫中的HTTP請求頭價值?

+0

*不要*使用HttpContext?使用控制器的重點在於數據通過控制器的參數。如果您的控制器使用HttpContext來讀取數據,就好像它是一個WebForms頁面一樣,您遇到了問題。 –

+0

@PanagiotisKanavos標題中的值是一條信息,指示該呼叫來自哪個移動設備。檢索正確的數據是很必要的。設備ID位於標題中,因爲身份驗證需要身份驗證,該身份驗證由自定義操作篩選器處理。我可以將設備ID作爲路由參數傳遞,但它可能是冗餘的 –

+0

檢查FromHeaderAttribute,但也檢查重複。 HttpContext現在可通過配置注入 –

回答

56

我能夠初始化的HttpContext和頭以這樣的方式

[TestMethod] 
public void TestValuesController() 
{ 
    ValuesController controller = new ValuesController(); 
    controller.ControllerContext = new ControllerContext(); 
    controller.ControllerContext.HttpContext = new DefaultHttpContext(); 
    controller.ControllerContext.HttpContext.Request.Headers["device-id"] = "20317"; 
    var result = controller.Get(); 
    //the controller correctly recieves the http header key value pair device-id:20317 
    ... 
} 
5

而不是嘲諷出來的HttpContext,它可能是一個更好的主意頭映射到該方法的參數。例如,在在此答案底部的控制器,所述id參數被設置爲具有等於「裝置ID」的名稱頭值...單元測試然後變成

[TestMethod] 
public void TestValuesController() 
{ 
    ValuesController controller = new ValuesController(); 
    var result = controller.GetHeaderValue("27"); 
    Assert.AreEqual(result, "27"); 
} 

當你可以模擬HttpContext,在我看來這是應該避免的,除非你別無選擇。 FromHeaderAttribute的文檔可以在這裏找到FromHeaderAttribute Class

public class ValuesController: Controller 
    { 

     public string GetHeaderValue([FromHeader(Name = "device-id")] string id) 
     { 
     return id; 
     } 
    } 
+0

在我的情況下,IIRC,它需要將它包含在http頭中,因爲需要評估相同的值在.net核心中間件組件中 –