ASP.Net MVC में नियंत्रक के अनुरोध को कैसे मॉक करें?


171

मेरे पास ASP # MVC फ्रेमवर्क का उपयोग करके C # में एक नियंत्रक है

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

मुझे मॉकिंग के बारे में कुछ सुझाव मिले और मैं निम्नलिखित और राइनोमॉक्स के साथ कोड का परीक्षण करने की उम्मीद कर रहा था

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

हालाँकि मुझे यह त्रुटि मिलती रहती है:

अपवाद सिस्टम। अर्गमेंटनैन्यूसेप्शन: सिस्टेम।अर्गमेंटन्यूल्स अपवाद: मान शून्य नहीं हो सकता। पैरामीटर नाम: System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest (HttpRequestBase अनुरोध) पर अनुरोध

चूंकि Requestनियंत्रक पर ऑब्जेक्ट का कोई सेटर नहीं है। मैंने नीचे दिए गए उत्तर से अनुशंसित कोड का उपयोग करके इस परीक्षण को ठीक से काम करने की कोशिश की।

यह राइनोमॉक्स के बजाय Moq का उपयोग करता है, और 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["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);

लेकिन निम्न त्रुटि प्राप्त करें:

अपवाद सिस्टम। क्रैगमेंट एक्ससेप्शन: System.ArgumentException: गैर-अप्रतिबंधित सदस्य पर अमान्य सेटअप: x => x.Headers [Mo-.Mock.ThrowIcantOverride (अभिव्यक्ति सेटअप, MethodInfo methodInfo) में।

फिर, ऐसा लगता है कि मैं अनुरोध हेडर सेट नहीं कर सकता। मैं RhinoMocks या Moq में यह मान कैसे सेट करूं?


Request.IsAjaxRequest को Request.IsAjaxRequest () के साथ बदलें
eu-ge-ne

Mock Request.Headers ["X-Requested-With"] या Request.IsAjaxRequest () के बजाय अनुरोध ["X-Requested-With"]। मैंने अपने प्रश्न को अपडेट किया है
-जे-एन-

जवाबों:


212

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

अपडेट:

इसके बजाय Request.Headers["X-Requested-With"]या नकली ।Request["X-Requested-With"]Request.IsAjaxRequest()


1
मुझे संदेश "ISetupGetter <T के लिए टाइप तर्क", TProperty> Moq.Met <T> .SetupGet <Tpropert> .... प्राप्त नहीं किया जा सकता है। कृपया प्रकार तर्क को स्पष्ट रूप से निर्दिष्ट करने का प्रयास करें। मैं किस प्रकार सेट करता हूं। 'var request =' हालांकि यह काम करने के लिए?
निसान

बस मेरे जवाब को अपडेट किया है - Request.IsAjaxRequest नहीं बल्कि Request.IsAjaxRequest ()। अपने प्रश्न को भी अपडेट करें
eu-ge-ne

फिर भी उत्पन्न करता है: अपवाद सिस्टम। क्रैगमेंट एक्ससेप्शन: System.ArgumentException: नॉन-ओवररिएडेबल मेंबर पर अमान्य सेटअप: x => x.IsAjaxRequest () Moq.Mock.Throw.ThfCantOverride (एक्सप्रेशन सेटअप, MethodInfo methodInfo)
निसान

समस्या यह है कि IsAjaxRequest () स्थैतिक विस्तार विधि है और इसका मजाक नहीं उड़ाया जा सकता - मैंने अपना उत्तर अपडेट कर दिया है।
यूरोप-जे-एन

संदर्भ होना चाहिए। SetupGet (x => x.Request)। पुनर्नियुक्ति (अनुरोध। संदर्भ); ऊपर दिया गया आपका कोड रिटर्न पर अभी भी 's' याद कर रहा है जिसके परिणामस्वरूप अपवाद System.ArgumentException: System.ArgumentException: गैर-अप्रतिबंधित सदस्य पर अमान्य सेटअप: x => x.Headers ["X-Requested-With"] Moq पर .Mock.ThrowIfCantOverride (अभिव्यक्ति सेटअप, MethodInfo methodInfo) त्रुटि संदेश
निसान

17

NSubstitute का उपयोग करने वाले किसी भी व्यक्ति के लिए मैं उपरोक्त उत्तरों को संशोधित करने और इस तरह से कुछ करने में सक्षम था ... (जहां विवरण नियंत्रक में एक्शन विधि का नाम है)

 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

यहाँ राइनोमॉक्स का उपयोग कर एक काम कर समाधान है। मैंने इसे Moq के समाधान पर आधारित पाया है जो मुझे 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);
}

5

क्या AjaxRequest एक विस्तार विधि है। तो आप इसे राइनो का उपयोग करके निम्न तरीके से कर सकते हैं:

    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

लगता है कि आप इस के लिए देख रहे हैं,

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

नियंत्रक में उपयोग:

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

3

आपको HttpContextBase का मखौल उड़ाना होगा और इसे अपनी नियंत्रक संपत्ति में डालना होगा, जैसे:

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

और क्या मजाक किया जाएगा। tje RequestContext ऑब्जेक्ट के लिए कंस्ट्रक्टर में एक HttpContextBase () ऑब्जेक्ट की आवश्यकता होती है, और HttpContextBase () में कोई भी कंस्ट्रक्टर नहीं होता है जो शून्य मापदंडों को स्वीकार करता है।
निसान

मैंने कोशिश की: var mocks = new MockRepository (); var mockedhttpContext = mocks.DynamicMock <HttpContextBase> (); var mockedHttpRequest = mocks.DynamicMock <HttpRequestBase> (); SetupResult.For (mockedhttpContext.Request) .Return (mockedHttpRequest); var नियंत्रक = नया होमकंट्रोलर (रिपॉजिटरी, लॉग इनइन्फोप्रोइडर); कंट्रोलर.कंट्रोलरकोटेक्स्ट = नया मॉकडॉटकनेक्ट, नया रूटडेटा (), कंट्रोलर); var result = नियंत्रक .ndex () ViewResult के रूप में; हालाँकि अभी भी वही अपवाद फेंका गया है।
निसान

आपका लिंक काम नहीं करता है, लेकिन निम्नलिखित काम करने लगता है _request.Setup (o => o.Form) .Rurnurns (नया NameValueCollection ());
वेडेक्स

2

IsAjaxRequest()यूनिट टेस्ट के दौरान गलत रिटर्न करने के लिए आपको अनुरोध हेडर और साथ ही नीचे दिए गए अनुसार अपने परीक्षण विधि में संग्रह मूल्य दोनों का अनुरोध करने की आवश्यकता है:

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

दोनों को स्थापित करने का कारण IsAjaxRequest () के कार्यान्वयन में छिपा है जो नीचे दिया गया है:

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

यह दोनों अनुरोध संग्रह और हेडर का उपयोग करता है यही कारण है कि हमें हेडर और अनुरोध संग्रह दोनों के लिए सेटअप बनाने की आवश्यकता है।

यह अजाक्स अनुरोध नहीं होने पर झूठी वापसी का अनुरोध करेगा। इसे सच करने के लिए आप निम्न कार्य कर सकते हैं:

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

0

मुझे वेब एपीआई के दौरान आपके अनुरोध में HttpRequestMessage ऑब्जेक्ट जोड़ने का अन्य तरीका मिला

[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

(पार्टी में थोड़ा लेट हो गया लेकिन मैं एक अलग रास्ते के लिए चला गया इसलिए सोचा कि मैं साझा करूँगा)

Http क्लासेस के लिए मॉक क्रिएट किए बिना इसे टेस्ट करने के एक शुद्ध कोड / मॉकिंग तरीके से जाने के लिए मैंने एक IControllerHelper को लागू किया जिसमें एक इनिशियलाइज़ विधि है जो एक पैरामीटर के रूप में रिक्वेस्ट को लेती है और फिर मेरे द्वारा वांछित गुणों को उजागर करती है जैसे:

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

फिर अपने कंट्रोलर में मैं विधि के शुरू में आरंभीकरण कहता हूं:

        _controllerHelper.Initialise(Request);

और फिर मेरा कोड केवल नकली निर्भरता पर निर्भर है।

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

कार्यात्मक परीक्षणों के लिए मैं सिर्फ एक विकल्प के लिए संरचना में iControllerHelper को ओवरराइड करता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.