Bagaimana cara mengejek HttpContext di ASP.NET MVC menggunakan Moq?


101
[TestMethod]
public void Home_Message_Display_Unknown_User_when_coockie_does_not_exist()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    context
        .Setup(c => c.Request)
        .Returns(request.Object);
    HomeController controller = new HomeController();

    controller.HttpContext = context; //Here I am getting an error (read only).
    ...
 }

kontroler dasar saya memiliki menimpa Initialize yang get's requestContext ini. Saya mencoba meneruskan ini tetapi saya tidak melakukan sesuatu dengan benar.

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
}

Di mana saya bisa mendapatkan informasi lebih lanjut tentang mengejek RequestContext dan HttpContext saya menggunakan Moq? Saya mencoba mengejek cookie dan konteks umum.

Jawaban:


61

HttpContext adalah read-only, tetapi sebenarnya berasal dari ControllerContext, yang dapat Anda setel.

 controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );

Yang ini bekerja untuk saya dengan mengizinkan saya menyetel HttpContext tiruan pada pengontrol.
Joel Malone

39

Buat permintaan, respons, dan tempatkan keduanya ke HttpContext:

HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);

Pertanyaannya adalah tentang * Kelas-kelas dasar, yaitu HttpRequestBase, bukan HttpRequest - saya tidak yakin mengapa keduanya dibutuhkan dan bahkan lebih menjengkelkan karena mereka "disegel". Tidak ada cara untuk menyetel LogonUserIdentity :(
Chris Kimpton

Jika mereka mengatur referensi saya, itu masih mungkin melalui remote, jadi seharusnya tidak menjadi masalah.
0100110010101

1
@ChrisKimpton: Sebagai upaya terakhir, selalu ada refleksi ;-)
Oliver

Ini berfungsi saat memasangnya ke controller, seperti ini: controller.ControllerContext = new ControllerContext (new HttpContextWrapper (httpContextMock), new RouteData (), controller);
Andreas Vendel

Iya. Anda memang dapat menyetel .LogonUserIdentity - _request.Setup (n => n.LogonUserIdentity) .Returns ((WindowsIdentity.GetCurrent));
KevinDeus

12

Terima kasih pengguna 0100110010101.

Itu berhasil untuk saya dan di sini saya memiliki masalah saat menulis kasus uji untuk kode di bawah ini:

 var currentUrl = Request.Url.AbsoluteUri;

Dan inilah garis yang memecahkan masalah tersebut

HomeController controller = new HomeController();
//Mock Request.Url.AbsoluteUri 
HttpRequest httpRequest = new HttpRequest("", "http://mySomething", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), new RouteData(), controller);

Mungkin bisa membantu yang lain.


Saya tidak bisa menggunakan tipe HttpRequest - apakah itu sesuatu yang lain sekarang?
Vincent Buscarello

1
Ini tidak berguna karena semua bidang di HttpRequest tidak berubah
A br

5

Inilah cara saya menggunakan ControllerContext untuk meneruskan jalur Aplikasi palsu:

[TestClass]
public class ClassTest
{
    private Mock<ControllerContext> mockControllerContext;
    private HomeController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        mockControllerContext = new Mock<ControllerContext>();
        sut = new HomeController();
    }
    [TestCleanup]
    public void TestCleanup()
    {
        sut.Dispose();
        mockControllerContext = null;
    }
    [TestMethod]
    public void Index_Should_Return_Default_View()
    {

        // Expectations
        mockControllerContext.SetupGet(x => x.HttpContext.Request.ApplicationPath)
            .Returns("/foo.com");
        sut.ControllerContext = mockControllerContext.Object;

        // Act
        var failure = sut.Index();

        // Assert
        Assert.IsInstanceOfType(failure, typeof(ViewResult), "Index() did not return expected ViewResult.");
    }
}

1
Mengapa Anda harus melewati jalur aplikasi palsu?
the_law

Kode MVC akan mengeksekusinya dan memunculkan pengecualian null jika tidak ada.
Joshua Ramirez

5

Berikut adalah contoh bagaimana Anda dapat mengatur ini: Mocking HttpContext HttpRequest dan HttpResponse untuk UnitTests (menggunakan Moq)

Perhatikan metode ekstensi yang sangat membantu menyederhanakan penggunaan kelas tiruan ini:

var mockHttpContext = new API_Moq_HttpContext();

var httpContext = mockHttpContext.httpContext();

httpContext.request_Write("<html><body>".line()); 
httpContext.request_Write("   this is a web page".line());  
httpContext.request_Write("</body></html>"); 

return httpContext.request_Read();

Berikut adalah contoh cara menulis Uji Unit menggunakan moq untuk memeriksa bahwa HttpModule berfungsi seperti yang diharapkan: Uji Unit untuk HttpModule menggunakan Moq untuk membungkus HttpRequest

Pembaruan: API ini telah difaktorkan ulang menjadi


Tautan rusak - harap sertakan kode dalam jawaban Anda
Hades
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.