Mock HttpContext สำหรับการทดสอบหน่วยตัวควบคุม. NET core MVC?


105

ฉันมีฟังก์ชันในคอนโทรลเลอร์ที่ฉันกำลังทดสอบหน่วยที่คาดหวังค่าในส่วนหัวของคำขอ http ฉันไม่สามารถเริ่มต้น HttpContext ได้เนื่องจากเป็นแบบอ่านอย่างเดียว

ฟังก์ชันคอนโทรลเลอร์ของฉันต้องการค่าส่วนหัวคำขอ http สำหรับ "device-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);
}

มีวิธีตรงไปตรงมาในการดำเนินการโดยไม่ใช้ไลบรารีของบุคคลที่สามหรือไม่?


1
ไม่ใช้ HttpContext? จุดรวมของการใช้คอนโทรลเลอร์คือข้อมูลที่มาจากพารามิเตอร์ของคอนโทรลเลอร์ หากคอนโทรลเลอร์ของคุณใช้ HttpContext เพื่ออ่านข้อมูลราวกับว่าเป็นหน้า WebForms แสดงว่าคุณมีปัญหา
Panagiotis Kanavos

@PanagiotisKanavos ค่าในส่วนหัวคือข้อมูลที่ระบุว่าโทรศัพท์มาจากอุปกรณ์มือถือใด นี่เป็นสิ่งจำเป็นในการดึงข้อมูลที่ถูกต้อง ID อุปกรณ์อยู่ในส่วนหัวเนื่องจาก ID จำเป็นสำหรับการตรวจสอบสิทธิ์ซึ่งจัดการโดยตัวกรองการดำเนินการที่กำหนดเอง ฉันสามารถส่งรหัสอุปกรณ์เป็นพารามิเตอร์เส้นทางได้ แต่มันจะซ้ำซ้อน
James Wierzba

ตรวจสอบ FromHeaderAttribute แต่ยังตรวจสอบรายการที่ซ้ำกัน HttpContext สามารถ
แทรก

1
ฉันขอแนะนำให้คุณแก้ไขคำถามเพื่อระบุสิ่งที่คุณต้องการอย่างแท้จริง (เข้าถึงช่องส่วนหัวเพื่อระบุอุปกรณ์เคลื่อนที่) เอกสาร ASP.NET ดูเหมือนจะผ่านช่วงเวลา .... "การเปลี่ยนแปลง" ที่จะทำให้มันเป็นไปอย่างดีโดยไม่มีหน้าเอกสาร ตรวจสอบคำถามที่เกือบจะเหมือนกันซึ่งถามวิธีกำหนดเส้นทางอุปกรณ์เคลื่อนที่
Panagiotis Kanavos

คำตอบ:


240

ฉันสามารถเริ่มต้น 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 receives the http header key value pair device-id:20317
    ...
}

20

แทนที่จะเยาะเย้ยบริบท HTTPC อาจเป็นความคิดที่ดีกว่าในการแมปส่วนหัวกับพารามิเตอร์บนเมธอด ตัวอย่างเช่นในตัวควบคุมที่ด้านล่างของคำตอบนี้idพารามิเตอร์จะถูกตั้งค่าเป็นส่วนหัวของค่าที่มีชื่อเท่ากับ "device-id" ... จากนั้นการทดสอบหน่วยจะกลายเป็น

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

ในขณะที่คุณสามารถล้อเลียน HttpContext ในความคิดของฉันมันเป็นสิ่งที่ควรหลีกเลี่ยงเว้นแต่คุณจะไม่มีทางเลือก เอกสารสำหรับ FromHeaderAttribute สามารถพบได้ที่นี่FromHeaderAttribute ชั้น

public class ValuesController: Controller
{
    public string GetHeaderValue([FromHeader(Name = "device-id")] string id)
    {
        return id;
    }
}

1
ในกรณีของฉัน IIRC จำเป็นต้องรวมไว้ในส่วนหัว http เนื่องจากค่าเดียวกันนี้จำเป็นต้องได้รับการประเมินในส่วนประกอบมิดเดิลแวร์. net core
James Wierzba
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.