ASP.Net MVC denetleyicisi isteği alay nasıl?


171

ASP.Net MVC çerçevesini kullanarak C # bir denetleyicisi var

public class HomeController:Controller{
  public ActionResult Index()
    {
      if (Request.IsAjaxRequest())
        { 
          //do some ajaxy stuff
        }
      return View("Index");
    }
}

Alay ile ilgili bazı ipuçları var ve aşağıdaki ve RhinoMocks ile kodu test etmek umuyordum

var mocks = new MockRepository();
var mockedhttpContext = mocks.DynamicMock<HttpContextBase>();
var mockedHttpRequest = mocks.DynamicMock<HttpRequestBase>();
SetupResult.For(mockedhttpContext.Request).Return(mockedHttpRequest);

var controller = new HomeController();
controller.ControllerContext = new ControllerContext(mockedhttpContext, new RouteData(), controller);
var result = controller.Index() as ViewResult;
Assert.AreEqual("About", result.ViewName);

Ancak bu hatayı almaya devam:

Özel Durum System.ArgumentNullException: System.ArgumentNullException: Değer boş olamaz. Parametre adı: System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest adresindeki istek (HttpRequestBase isteği)

Yana Requestdenetleyicisinde nesnenin bir ayarlayıcı sahiptir. Aşağıdaki testten önerilen kodu kullanarak bu testi düzgün bir şekilde çalışmaya çalıştım.

Bu, RhinoMocks yerine Moq kullandı ve Moq kullanırken aynı test için aşağıdakileri kullanıyorum:

var request = new Mock<HttpRequestBase>();
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers["X-Requested-With"]).Returns("XMLHttpRequest");

var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
var controller = new HomeController(Repository, LoginInfoProvider);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
var result = controller.Index() as ViewResult;
Assert.AreEqual("About", result.ViewName);

ancak aşağıdaki hatayı alın:

Özel Durum System.ArgumentException: System.ArgumentException: Geçersiz kılınamayan bir üye için geçersiz kurulum: x => x.Headers ["X-Requested-With"], Moq.Mock.ThrowIfCantOverride (İfade kurulumu, MethodInfo methodInfo)

Yine, istek başlığını ayarlayamıyorum gibi görünüyor. RhinoMocks veya Moq'da bu değeri nasıl ayarlarım?


Request.IsAjaxRequest yerine Request.IsAjaxRequest () ile değiştir
eu-ge-ne

Alay Request.Headers Request.IsAjaxRequest () yerine ["X-Requested-With"] veya Request ["X-Requested-With"]. Sorumu güncelledim
eu-ge-ne

Yanıtlar:


212

Adedi Kullanma :

var request = new Mock<HttpRequestBase>();
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers).Returns(
    new System.Net.WebHeaderCollection {
        {"X-Requested-With", "XMLHttpRequest"}
    });

var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);

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

GÜNCELLENMİŞ:

Sahte Request.Headers["X-Requested-With"]veya Request["X-Requested-With"]yerine Request.IsAjaxRequest().


1
"ISetupGetter <T, TProperty> Moq.Mock <T> yöntemi için Type bağımsız değişkeni .SetupGet <Tpropert> .... uage'den çıkartılamaz. Tür bağımsız değişkenlerini açıkça belirtmeyi deneyin. 'var request =' bunu işe almak için olsa?
Nissan

Cevabımı güncelledim - Request.IsAjaxRequest değil, Request.IsAjaxRequest (). Sorunuzu da güncelleyin
eu-ge-ne

Yine de üretir: Exception System.ArgumentException: System.ArgumentException: Geçersiz kılınamayan bir üye için geçersiz kurulum: x => x.IsAjaxRequest (), Moq.Mock.ThrowIfCantOverride (İfade kurulumu, MethodInfo methodInfo)
Nissan

Sorun IsAjaxRequest () statik uzantısı yöntemi ve alay edilemez olmasıdır - Cevabımı güncelledim.
eu-ge-ne

bağlam olmalıdır.SetupGet (x => x.Request) .Returns (request.Object); yukarıdaki kodunuz Dönüşte hala 's' eksik Ayrıca System.ArgumentException: System.ArgumentException: Moq'da geçersiz kılınamayan bir üye için geçersiz kurulum: x => x.Headers ["X-Requested-With"] Adedi .Mock.ThrowIfCantOverride (İfade kurulumu, MethodInfo methodInfo) hata mesajı
Nissan

17

NSubstitute kullanan herkes için yukarıdaki cevapları değiştirebildim ve böyle bir şey yapabildim ... (Ayrıntılar, denetleyicideki Eylem yöntemi adıdır)

 var fakeRequest = Substitute.For<HttpRequestBase>();
        var fakeContext = Substitute.For<HttpContextBase>();
        fakeRequest.Headers.Returns(new WebHeaderCollection { {"X-Requested-With", "XMLHttpRequest"}});
        fakeContext.Request.Returns(fakeRequest);
        controller.ControllerContext = new ControllerContext(fakeContext, new RouteData(), controller);
        var model = new EntityTypeMaintenanceModel();

        var result = controller.Details(model) as PartialViewResult;

        Assert.IsNotNull(result);
        Assert.AreEqual("EntityType", result.ViewName);

13

İşte RhinoMocks kullanarak çalışan bir çözüm. Ben http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/ adresinde bulduğum bir Moq çözümüne dayandım

public static void MakeAjaxRequest(this Controller controller)
{
        MockRepository mocks = new MockRepository();

        // Create mocks
        var mockedhttpContext = mocks.DynamicMock<HttpContextBase>();
        var mockedHttpRequest = mocks.DynamicMock<HttpRequestBase>();

        // Set headers to pretend it's an Ajax request
        SetupResult.For(mockedHttpRequest.Headers)
            .Return(new WebHeaderCollection() {
                {"X-Requested-With", "XMLHttpRequest"}
            });

        // Tell the mocked context to return the mocked request
        SetupResult.For(mockedhttpContext.Request).Return(mockedHttpRequest);

        mocks.ReplayAll();

        // Set controllerContext
        controller.ControllerContext = new ControllerContext(mockedhttpContext, new RouteData(), controller);
}

5

AjaxRequest bir uzantı yöntemidir. Böylece Rhino'yu kullanarak şu şekilde yapabilirsiniz:

    protected HttpContextBase BuildHttpContextStub(bool isAjaxRequest)
    {
        var httpRequestBase = MockRepository.GenerateStub<HttpRequestBase>();   
        if (isAjaxRequest)
        {
            httpRequestBase.Stub(r => r["X-Requested-With"]).Return("XMLHttpRequest");
        }

        var httpContextBase = MockRepository.GenerateStub<HttpContextBase>();
        httpContextBase.Stub(c => c.Request).Return(httpRequestBase);

        return httpContextBase;
    }

    // Build controller
    ....
    controller.ControllerContext = new ControllerContext(BuildHttpContextStub(true), new RouteData(), controller);

4

Bunu aradığınız anlaşılıyor,

 var requestMock = new Mock<HttpRequestBase>();
 requestMock.SetupGet(rq => rq["Age"]).Returns("2001");

Denetleyicide Kullanım:

 public ActionResult Index()
 {
        var age = Request["Age"]; //This will return 2001
 }

3

HttpContextBase ile alay etmeli ve ControllerContext özelliğinize şu şekilde koymalısınız:

controller.ControllerContext = 
new ControllerContext(mockedHttpContext, new RouteData(), controller);

ve mockedHttpContext'in alay edilmesi gerekir? tje RequestContext nesnesinin yapıcıda bir HttpContextBase () nesnesine ihtiyacı vardır ve HttpContextBase () öğesinde sıfır parametresini kabul eden bir yapıcı yoktur.
Nissan

Denedim: var mocks = yeni MockRepository (); var mockedhttpContext = mocks.DynamicMock <HttpContextBase> (); var mockedHttpRequest = mocks.DynamicMock <HttpRequestBase> (); SetupResult.For (mockedhttpContext.Request) .Return (mockedHttpRequest); var controller = yeni HomeController (Depo, LoginInfoProvider); controller.ControllerContext = yeni mockedhttpContext, yeni RouteData (), denetleyici); varres = ViewResult olarak controller.Index (); Ancak yine de aynı istisna atılır.
Nissan

Bağlantınız çalışmıyor, ancak aşağıdakiler _request.Setup (o => o.Form) gibi görünüyor .Returns (new NameValueCollection ());
Vdex

2

Yapmak için IsAjaxRequest()aşağıda verildiği gibi Birim test sırasında return false için iyi istek toplama değeri hem test yönteminde olduğu kadar kurulum talep Başlıkları gerekir:

_request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection { { "X-Requested-With", "NotAjaxRequest" } });
_request.SetupGet(x=>x["X-Requested-With"]).Returns("NotAjaxRequest");

Her ikisini de ayarlama nedeni, aşağıda verilen IsAjaxRequest () uygulamasında gizlidir:

public static bool IsAjaxRequest(this HttpRequestBase request)<br/>
{ 
    if (request == null)
    {
        throw new ArgumentNullException("request");
    }
    return ((request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest")));
}

Hem istek Toplama hem de başlık kullanır, bu nedenle hem Başlık hem de İstek Toplama için kurulum oluşturmamız gerekir.

bu, bir ajax isteği olmadığında yanlış dönüş isteğinde bulunacaktır. geri dönmesini sağlamak için aşağıdakileri yapabilirsiniz:

_httpContext.SetupGet(x => x.Request["X-Requested-With"]).Returns("XMLHttpRequest");

0

Aşağıdaki gibi Web API sırasında isteğinize bir HttpRequestMessage nesnesi eklemek için başka bir yol buldum

[Test]
public void TestMethod()
{
    var controllerContext = new HttpControllerContext();
    var request = new HttpRequestMessage();
    request.Headers.Add("TestHeader", "TestHeader");
    controllerContext.Request = request;
    _controller.ControllerContext = controllerContext;

    var result = _controller.YourAPIMethod();
    //Your assertion
}

0

(Partiye biraz geç ama farklı bir rotaya gittim, bu yüzden paylaşacağımı düşündüm)

Http sınıfları için alay oluşturmadan bu test saf bir kod / alay yolu için gitmek için I parametre olarak istek ve daha sonra istediğiniz özellikleri maruz alır bir Initialise yöntemi olan bir IControllerHelper uyguladı:

    public interface IControllerHelper
    {
        void Initialise(HttpRequest request);
        string HostAddress { get; }
    }

    public class ControllerHelper : IControllerHelper
    {
        private HttpRequest _request;
        
        public void Initialise(HttpRequest request)
        {
            _request = request;
        }

        public string HostAddress =>  _request.GetUri().GetLeftPart(UriPartial.Authority);
    }

Sonra denetleyicimde yöntemin başlangıcında başlatma çağırıyorum:

        _controllerHelper.Initialise(Request);

Ve sonra kodum sadece takılabilir güvenilirliklere bağlı.

        return Created(new Uri($"{_controllerHelper.HostName}/api/MyEndpoint/{result.id}"), result);

Fonksiyonel testler için, sadece bir ikame için kompozisyondaki iControllerHelper'ı geçersiz kıldım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.