Mengolok-olok HttpContext untuk pengujian unit pengontrol MVC inti .NET?

103

Saya memiliki fungsi dalam pengontrol yang saya uji unit yang mengharapkan nilai di header permintaan http. Saya tidak dapat menginisialisasi HttpContext karena hanya bisa dibaca.

Fungsi pengontrol saya mengharapkan nilai header permintaan http untuk "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);
}

Apakah ada cara mudah untuk melakukan ini tanpa menggunakan perpustakaan pihak ketiga?

James Wierzba
sumber
1
Jangan gunakan HttpContext? Inti dari menggunakan pengontrol adalah bahwa data datang melalui parameter pengontrol. Jika pengontrol Anda menggunakan HttpContext untuk membaca data seolah-olah itu adalah halaman WebForms, Anda memiliki masalah.
Panagiotis Kanavos
@PanagiotisKanavos Nilai di header adalah bagian informasi yang menunjukkan dari perangkat seluler mana panggilan tersebut berasal. Ini diperlukan untuk mengambil data yang benar. ID perangkat ada di header karena ID diperlukan untuk autentikasi, yang ditangani oleh filter tindakan kustom. Saya bisa memberikan ID perangkat sebagai parameter rute tetapi itu akan berlebihan
James Wierzba
Periksa FromHeaderAttribute tetapi juga periksa duplikatnya. HttpContext dapat disuntikkan melalui konfigurasi sekarang
Panagiotis Kanavos
1
Saya sarankan Anda mengedit pertanyaan Anda untuk menentukan dengan tepat apa yang Anda inginkan (akses ke bidang tajuk untuk mengidentifikasi perangkat seluler). Dokumentasi ASP.NET tampaknya akan melalui masa .... "transisi" untuk membuatnya lebih baik, dengan halaman dokumentasi hilang. Periksa pertanyaan yang hampir identik ini yang menanyakan cara merutekan perangkat seluler
Panagiotis Kanavos

Jawaban:

236

Saya dapat menginisialisasi httpcontext dan header dengan cara ini:

[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
    ...
}
James Wierzba
sumber
20

Daripada mengejek HTTPContext, lebih baik memetakan header menjadi parameter pada metode. Misalnya, di pengontrol di bagian bawah jawaban ini, idparameter disetel ke header nilai dengan nama yang sama dengan "device-id" ... Tes unit kemudian menjadi

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

Meskipun Anda dapat mengejek HttpContext, menurut saya itu adalah sesuatu yang harus dihindari kecuali Anda tidak punya pilihan. Dokumentasi untuk FromHeaderAttribute dapat ditemukan di sini Kelas FromHeaderAttribute .

public class ValuesController: Controller
{
    public string GetHeaderValue([FromHeader(Name = "device-id")] string id)
    {
        return id;
    }
}
GlennSills
sumber
1
Dalam kasus saya, IIRC, itu adalah persyaratan untuk memasukkannya ke dalam http header karena nilai yang sama perlu dievaluasi dalam komponen middleware inti .net
James Wierzba