2008-08-28 19 views
62

तो नियंत्रक संदर्भ कुछ asp.net internals पर निर्भर करता है। इकाई परीक्षणों के लिए इन्हें साफ करने के कुछ तरीके क्या हैं? सेटअप के टन के साथ परीक्षण को अवरुद्ध करने के लिए जब मैं केवल जरूरत है उदाहरण के लिए, अपने बहुत ही आसान की तरह लगता है, Request.HttpMethod वापस जाने के लिए "GET"।मजाक Asp.net-MVC नियंत्रक संदर्भ

मैं नेट पर कुछ उदाहरण/सहायकों बाहर देखा है, लेकिन कुछ दिनांकित हैं। यह नवीनतम और महानतम रखने के लिए यह एक अच्छी जगह होगी।

मैं राइनो के नवीनतम संस्करण का उपयोग कर रहा मजाक उड़ाता है

+0

मैं ऐसा करने पर विचार कर रहा था। लेकिन केवल डेटाबेस कनेक्शन के लिए नकली की जरूरत है। डेटाबेस मैपिंग का परीक्षण करने के बजाय मैंने फ़ंक्शन को नियमित कक्षा में स्थानांतरित कर दिया और डेटाबेस कनेक्शन के बिना उस फ़ंक्शन का परीक्षण किया। – MrFox

उत्तर

58

MOQ का उपयोग करना यह कुछ इस तरह दिखता है:

var request = new Mock<HttpRequestBase>(); 
request.Expect(r => r.HttpMethod).Returns("GET"); 
var mockHttpContext = new Mock<HttpContextBase>(); 
mockHttpContext.Expect(c => c.Request).Returns(request.Object); 
var controllerContext = new ControllerContext(mockHttpContext.Object 
, new RouteData(), new Mock<ControllerBase>().Object); 

मुझे लगता है कि राइनो Mocks वाक्य रचना के समान है।

+16

यह अब एमवीसी 3 में मान्य नहीं है। रिक्त रूटडेटा में पास होने से अपवाद फेंक देंगे जब गैर-वर्चुअल, गैर-नकली विधि GetRequiredString को रूटडेटा पर कॉल किया जाता है। – ScottKoon

+2

@ स्कॉटकून कृपया – Jon

+1

जैसा दिखाना चाहिए इसका एक डेमो प्रदान करें इस प्रश्न का उत्तर आपको रूटडेटा को नकल करने का तरीका दिखाता है। http://stackoverflow.com/questions/986183/mocking-the-routedata-class-in-system-web-routing-for-mvc-applications – ScottKoon

1

मुझे लगता है कि लंबे समय से मजाक प्रक्रिया बहुत ज्यादा घर्षण होने के लिए लगता है।

एक वास्तविक प्रोजेक्ट पर एएसपी.नेट एमवीसी का उपयोग करने का सबसे अच्छा तरीका - HttpContext को IWebContext इंटरफ़ेस में सार करना है जो बस गुजरता है। फिर आप IWebContext को बिना दर्द के नकल कर सकते हैं।

यहाँ एक example

+1

क्या आप इसे थोड़ा और समझा सकते हैं? – user40097

17

है यहाँ जेसन के लिंक से एक टुकड़ा है। यह फिल की विधि के समान है लेकिन गैंडो का उपयोग करता है।

नोट: mockHttpContext.Request mockRequest वापस जाने के लिए पहले mockRequest के internals बाहर टोंटदार रहे टोंटदार है। मुझे विश्वास है कि यह आदेश आवश्यक है।

// create a fake web context 
var mockHttpContext = MockRepository.GenerateMock<HttpContextBase>(); 
var mockRequest = MockRepository.GenerateMock<HttpRequestBase>(); 
mockHttpContext.Stub(x => x.Request).Return(mockRequest); 

// tell the mock to return "GET" when HttpMethod is called 
mockRequest.Stub(x => x.HttpMethod).Return("GET");    

var controller = new AccountController(); 

// assign the fake context 
var context = new ControllerContext(mockHttpContext, 
        new RouteData(), 
        controller); 
controller.ControllerContext = context; 

// act 
... 
2

मैं इस कल्पना

public abstract class Specification <C> where C: Controller 
{ 
    protected C controller; 

    HttpContextBase mockHttpContext; 
    HttpRequestBase mockRequest; 

    protected Exception ExceptionThrown { get; private set; } 

    [SetUp] 
    public void Setup() 
    { 
     mockHttpContext = MockRepository.GenerateMock<HttpContextBase>(); 
     mockRequest = MockRepository.GenerateMock<HttpRequestBase>(); 

     mockHttpContext.Stub(x => x.Request).Return(mockRequest); 
     mockRequest.Stub(x => x.HttpMethod).Return("GET"); 


     EstablishContext(); 
     SetHttpContext(); 

     try 
     { 
      When(); 
     } 
     catch (Exception exc) 
     { 
      ExceptionThrown = exc; 
     } 
    } 

    protected void SetHttpContext() 
    { 
     var context = new ControllerContext(mockHttpContext, new RouteData(), controller); 
     controller.ControllerContext = context; 
    } 

    protected T Mock<T>() where T: class 
    { 
     return MockRepository.GenerateMock<T>(); 
    } 

    protected abstract void EstablishContext(); 
    protected abstract void When(); 

    [TearDown] 
    public virtual void TearDown() 
    { 
    } 
} 

साथ समाप्त किया है और रस यहाँ है

[TestFixture] 
public class When_invoking_ManageUsersControllers_Update :Specification <ManageUsersController> 
{ 
    private IUserRepository userRepository; 
    FormCollection form; 

    ActionResult result; 
    User retUser; 

    protected override void EstablishContext() 
    { 
     userRepository = Mock<IUserRepository>(); 
     controller = new ManageUsersController(userRepository); 

     retUser = new User(); 
     userRepository.Expect(x => x.GetById(5)).Return(retUser); 
     userRepository.Expect(x => x.Update(retUser)); 

     form = new FormCollection(); 
     form["IdUser"] = 5.ToString(); 
     form["Name"] = 5.ToString(); 
     form["Surename"] = 5.ToString(); 
     form["Login"] = 5.ToString(); 
     form["Password"] = 5.ToString(); 
    } 

    protected override void When() 
    { 
     result = controller.Edit(5, form); 
    } 

    [Test] 
    public void is_retrieved_before_update_original_user() 
    { 
     userRepository.AssertWasCalled(x => x.GetById(5)); 
     userRepository.AssertWasCalled(x => x.Update(retUser)); 
    } 
} 

7

का आनंद या आप कोई आवश्यकता नहीं होती Typemock अलगाने साथ ऐसा कर सकते सभी में एक नकली नियंत्रक में भेजने के लिए:

Isolate.WhenCalled(()=>HttpContext.Request.HttpMethod).WillReturn("Get"); 
9

ऐसा लगता है कि एमवीसी 2 (मैं आरसी 1 का उपयोग कर रहा हूं) में थोड़ा बदलाव आया है। यदि कार्रवाई के लिए एक विशिष्ट विधि ([HttpPost], [HttpGet]) की आवश्यकता होती है तो फिल हैक का समाधान मेरे लिए काम नहीं करता है। रिफ्लेक्टर में चारों ओर घूमते हुए, ऐसा लगता है कि इन विशेषताओं को सत्यापित करने की विधि बदल गई है। MVC अब request.Headers, request.Form, और एक X-HTTP-Method-Override मूल्य के लिए request.QueryString जाँच करता है।

आप इन गुणों के लिए mocks जोड़ देते हैं तो यह काम करता है:

var request = new Mock<HttpRequestBase>(); 
request.Setup(r => r.HttpMethod).Returns("POST"); 
request.Setup(r => r.Headers).Returns(new NameValueCollection()); 
request.Setup(r => r.Form).Returns(new NameValueCollection()); 
request.Setup(r => r.QueryString).Returns(new NameValueCollection()); 

var mockHttpContext = new Mock<HttpContextBase>(); 
mockHttpContext.Expect(c => c.Request).Returns(request.Object); 
var controllerContext = new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object); 
+1

यह मेरे लिए काम करता है, हालांकि एमवीसी 2 आरसी में मुझे निम्नलिखित भी जोड़ना पड़ता था: अनुरोध। सेटअप (आर => आर। फाइल)। रीटर्न्स (नया मॉक <एचटीपीफ़ाइलकोलेक्शनबेस>() ऑब्जेक्ट); अन्यथा मुझे nullreferenceexception –

19

यहाँ जो HttpRequest और HttpResponse वस्तुओं का मजाक उड़ाता है एक नमूना इकाई परीक्षण वर्ग MSTest और Moq उपयोग कर रहा है। (.NET 4.0, एएसपी.नेट एमवीसी 3.0)

नियंत्रक कार्रवाई अनुरोध से मूल्य प्राप्त करती है और प्रतिक्रिया ऑब्जेक्ट्स में http शीर्षलेख सेट करती है।अन्य http संदर्भ ऑब्जेक्ट्स को उसी तरह से मजाक किया जा सकता है

[TestClass] 
public class MyControllerTest 
{ 
    protected Mock<HttpContextBase> HttpContextBaseMock; 
    protected Mock<HttpRequestBase> HttpRequestMock; 
    protected Mock<HttpResponseBase> HttpResponseMock; 

    [TestInitialize] 
    public void TestInitialize() 
    { 
     HttpContextBaseMock = new Mock<HttpContextBase>(); 
     HttpRequestMock = new Mock<HttpRequestBase>(); 
     HttpResponseMock = new Mock<HttpResponseBase>(); 
     HttpContextBaseMock.SetupGet(x => x.Request).Returns(HttpRequestMock.Object); 
     HttpContextBaseMock.SetupGet(x => x.Response).Returns(HttpResponseMock.Object); 
    } 

    protected MyController SetupController() 
    { 
     var routes = new RouteCollection(); 
     var controller = new MyController(); 
     controller.ControllerContext = new ControllerContext(HttpContextBaseMock.Object, new RouteData(), controller); 
     controller.Url = new UrlHelper(new RequestContext(HttpContextBaseMock.Object, new RouteData()), routes); 
     return controller; 
    } 

    [TestMethod] 
    public void IndexTest() 
    { 
     HttpRequestMock.Setup(x => x["x"]).Returns("1"); 
     HttpResponseMock.Setup(x => x.AddHeader("name", "value")); 

     var controller = SetupController(); 
     var result = controller.Index(); 
     Assert.AreEqual("1", result.Content); 

     HttpRequestMock.VerifyAll(); 
     HttpResponseMock.VerifyAll(); 
    } 
} 

public class MyController : Controller 
{ 
    public ContentResult Index() 
    { 
     var x = Request["x"]; 
     Response.AddHeader("name", "value"); 
     return Content(x); 
    } 
} 
+0

मिलता है, बहुत से धन्यवाद! इसने मेरी बहुत मदद की। काश मैं इसे दस बार ऊपर उठा सकता हूं। –

+0

@ मैक्सिम कोज़लेन्को कई, बहुत धन्यवाद। इसने मेरी बहुत मदद की –

संबंधित मुद्दे