Note that there are some explanatory texts on larger screens.

plurals
  1. POUnit test or runtime ActionResult string output response via ExecuteResult?
    primarykey
    data
    text
    <h1>The Question...</h1> <p>What is the best way to Unit Test the <strong>string response</strong> and <strong>content type</strong> from several Controller methods?</p> <h2>Using...</h2> <p>Each method returns an <code>ActionResult</code>, some of which are <code>ViewResult</code> responses. I'm using ASP.NET <strong>MVC 2</strong> RTM and <strong>Moq</strong>.</p> <h2>Specifically...</h2> <p>I wish to obtain the <code>TextWriter</code> from <code>HttpContext.Response</code> and have it contain the full string response from an <code>ActionResult</code>.</p> <h2>Why?</h2> <h3>1. Within Unit Tests</h3> <p>I want to test some specific if content <strong>does</strong> and <strong>does not</strong> exist with the output.</p> <h3>2. Runtime via worker thread</h3> <p>I use a background worker thread to update static content on remote servers, this content is the output from the Controllers and must be generated as such. Making requests to the same server via HTTP is not advisable because there are many 1000's of files which are updated.</p> <p>I see the same code being used at both <em>Runtime</em> and via <em>Unit Tests</em>, as it would be very similar?</p> <h2>Stumbling block 1</h2> <p>How to correctly setup mocking to not require Routes <strong>Or</strong> call <code>RegisterRoutes</code> and <code>RegisterAllAreas</code> have the call succeed, currently throws an exception deep inside <code>BuildManagerWrapper::IBuildManager.GetReferencedAssemblies</code>.</p> <h1>Sample Code</h1> <h3>My mocking helpers look like this:</h3> <pre><code>public static HttpContextBase FakeHttpContext() { var context = new Mock&lt;HttpContextBase&gt;(); var request = new Mock&lt;HttpRequestBase&gt;(); var response = new Mock&lt;HttpResponseBase&gt;(); var session = new Mock&lt;HttpSessionStateBase&gt;(); var server = new Mock&lt;HttpServerUtilityBase&gt;(); var writer = new StringWriter(); var form = new NameValueCollection(); var queryString = new NameValueCollection(); request.Setup(r =&gt; r.Form).Returns(form); request.Setup(r =&gt; r.QueryString).Returns(queryString); context.Setup(ctx =&gt; ctx.Request).Returns(request.Object); context.Setup(ctx =&gt; ctx.Response).Returns(response.Object); context.Setup(ctx =&gt; ctx.Session).Returns(session.Object); context.Setup(ctx =&gt; ctx.Server).Returns(server.Object); context.Setup(ctx =&gt; ctx.Response.Output).Returns(writer); return context.Object; } public static void SetFakeControllerContext(this Controller controller) { var httpContext = FakeHttpContext(); var routeData = new RouteData(); var routeData = RouteTable.Routes.GetRouteData(httpContext); ControllerContext context = new ControllerContext(new RequestContext(httpContext, routeData), controller); controller.ControllerContext = context; } </code></pre> <h3>And my current attempt at a TestMethod is as follows:</h3> <pre><code>[TestMethod] public void CodedJavaScriptAction_Should_Return_JavaScript_Response() { // Arrange var controller = new CodedController(); controller.SetFakeControllerContext(); // Act var result = controller.CodedJavaScript(); // Response is made up as a ViewResult containing JavaScript. var controllerContext = controller.ControllerContext; var routeData = controllerContext.RouteData; routeData.DataTokens.Add("area", "Coded"); routeData.Values.Add("area", "Coded"); routeData.Values.Add("controller", "Coded"); routeData.Values.Add("action", "CodedJavaScript"); var response = controllerContext.HttpContext.Response; response.Buffer = true; var vr = result as ViewResult; vr.MasterName = "CodedJavaScript"; result.ExecuteResult(controllerContext); // Assert var s = response.Output.ToString(); Assert.AreEqual("text/javascript", response.ContentType); Assert.IsTrue(s.Length &gt; 0); // @todo: Further tests to be added here. } </code></pre> <h3>My area, views and shared files are:</h3> <p>-<code>Areas\Coded\Controllers\CodeController.cs</code><br> -<code>Areas\Coded\Views\Coded\CodedJavaScript.aspx</code><br> -<code>Areas\Coded\CodedAreaRegistration.cs</code><br> -<code>Views\Shared\CodedJavaScript.Master</code> </p> <p><strong>EDIT</strong>: edited to now include both Unit Testing and Runtime execution. Thanks to @Darin Dimitrov for mentioning <em>Integration Testing</em> but there is now also a runtime element to this question.</p> <p><strong>EDIT</strong>: After some testing and review using some of the source code from <a href="https://stackoverflow.com/questions/4216349/unit-test-or-runtime-actionresult-string-output-response-via-executeresult/4233968#4233968">MvcIntegrationTestFramework as referenced by alexn</a>. Which uses <code>AppDomain.CreateDomain</code> and <code>SimpleWorkerRequest</code> to create a new request, I have found that it is not possible to create a new request via this method in a process that already has an active request, due to <code>static</code> values used. So this rules this method out.</p> <p>Probably the same issue but I am now wondering if the result from a <strong>Partial View</strong> can be returned as a string more directly?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload