web-dev-qa-db-fra.com

Comment simuler la requête sur le contrôleur dans ASP.Net MVC?

J'ai un contrôleur en C # utilisant le framework ASP.Net MVC

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

J'ai eu quelques conseils pour me moquer et j'espérais tester le code avec ce qui suit et RhinoMocks

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);

Cependant, je continue à avoir cette erreur:

Exception System.ArgumentNullException: System.ArgumentNullException: valeur ne peut pas être nulle. Le nom du paramètre: demander à System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest (requête HttpRequestBase )

Depuis l'objet Request sur le contrôleur n'a aucun setter. J'ai essayé de faire fonctionner ce test correctement en utilisant le code recommandé dans la réponse ci-dessous.

Cela utilisait Moq au lieu de RhinoMocks, et en utilisant Moq, j'utilise les éléments suivants pour le même test:

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);

mais obtenez l'erreur suivante:

Exception System.ArgumentException: System.ArgumentException: invalide configuration sur un membre non remplaçable: x => x.Headers ["X-Requested-With"] sur Moq.Mock.ThrowIfCantOverride (Expression setup, MethodInfo methodInfo)

Encore une fois, il semble que je ne puisse pas définir l'en-tête de la demande . Comment définir cette valeur, dans RhinoMocks ou Moq?

156
Nissan

Utiliser Moq :

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);

MIS À JOUR:

Mockez Request.Headers["X-Requested-With"] ou Request["X-Requested-With"] au lieu de Request.IsAjaxRequest().

198
eu-ge-ne

Pour quiconque utilisant NSubstitute, j'ai pu modifier les réponses ci-dessus et faire quelque chose comme ceci ... (où Details est le nom de la méthode Action sur le contrôleur)

 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);
15
sjmarsh

Voici une solution de travail utilisant RhinoMocks. Je l’ai basée sur une solution Moq trouvée à http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/

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);
}
13
Phil Hale

AjaxRequest est-il une méthode d'extension? Vous pouvez donc le faire de la manière suivante en utilisant Rhino:

    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);
5
Jeroen Bernsen

On dirait que tu cherches ça,

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

Utilisation dans le contrôleur:

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

Vous devez vous moquer de HttpContextBase et le placer dans votre propriété ControllerContext, comme ceci:

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

Pour que IsAjaxRequest() puisse retourner false lors du test d'unité, vous devez configurer les en-têtes de requête ainsi que la valeur de collecte des requêtes dans votre méthode de test, comme indiqué ci-dessous:

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

La raison pour configurer les deux est cachée dans l'implémentation de IsAjaxRequest () qui est donnée ci-dessous:

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")));
}

Il utilise à la fois request Collection et header c'est pourquoi nous devons créer une configuration pour Header et Request Collection.

cela fera la demande pour retourner false quand ce n'est pas une demande ajax. pour le rendre vrai, vous pouvez effectuer les opérations suivantes:

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

J'ai trouvé un autre moyen d'ajouter un objet HttpRequestMessage à votre demande lors de l'API Web, comme suit:

[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
Niraj Trivedi