Code: Impossible

Testing JsonResult in Asp.net MVC

So lately I’ve been working on a project using Asp.net MVC and TDD to build a web 2.0 application. It’s a twitter-like application that I started a while ago but due to my failure to test everything I lost about 99% of my work and had to start over from scratch.

But this was sort of a good thing because it gave me a chance to revisit a lot of things that I wasn’t very happy with the first time around. I just got done adding the ability for users to post new messages via AJAX.

In the first version of the application a user would type their status into a textbox, click submit and the page would refresh with their new message at the top of their user wall. Although functional this wasn’t exactly very “web 2.0″-ish.

My controller will have an action called Index that takes two parameters, the message the users is posting and the tags associated with that message. m_UserService, and m_MessageService are private objects, that interact with the database.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string message, string[] tags)
{

	var messageOwner = this.m_UserService
		.GetByUserName(User.Identity.Name);

	var messageObj = new Message()
	{
		Owner = new User()
		{
			Identifier = messageOwner.Identifier,
			UserName = messageOwner.UserName,
			Email = messageOwner.Email,
			RealName = messageOwner.RealName,
			IsModerator = messageOwner.IsModerator
		},
		Body = message,
		CreatedOn = DateTime.Now,
		IsReply = message.StartsWith("@")
	};

	this.m_MessageService.Post(messageObj);

	return Json(messageObj);
}

The JsonResult will be serialized/deserialized by the MVC framework when the code is run in a web project or IIS but I need to be able to test this as part of our build process.

* NOTE: For those of you who might be thinking “how do we get around the authorization”? I’ll answer that in a later post (or you can check out Scott Hanselmans blog for the solution).

Ideally I wanted to do something like the following in my test:

	Assert.AreEqual("some text", jsonObject.someproperty);

But since C# is a type-safe language this isn’t easily doable. However, utilizing an extension method and the JavaScriptSerializer in System.Web.Script.Serialization we can come pretty close:

	Assert.AreEqual("some text", jsonObject["someproperty"]);

Here is the code I used to achieve this (This code depends on Moq v3.0.108.5 which you can download here):

using System;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Mvc;

using Moq;

public static class JsonResultExtensions
{

	public static T Deserialize<T>(this JsonResult json,
		Controller controller)
	{

		var jsonSB = new StringBuilder();

		var httpResponseMock =
			new Mock<httpResponseBase>();

		httpResponseMock.Setup(mock => {
			mock.Write(It.IsAny<string>());
		}).Callback<string>((s) => {
			jsonSB.Append(s);
		});

		var httpContextMock =  new Mock<httpContextBase>();

		httpContextMock.Setup(mock => mock.Response)
			.Returns(httpResponseMock.Object);

		controller.ControllerContext
			.HttpContext = httpContextMock.Object;

		jsonResult.ExecuteResult(
			controller.ControllerContext);

		return new JavaScriptSerializer()
			.Deserialize<T>(jsonSB.ToString());
	}
}

Tags: , ,

4 Responses to “Testing JsonResult in Asp.net MVC”

  1. ASP.NET MVC Archived Blog Posts, Page 1 Says:

    [...] to VoteTesting JsonResult in Asp.net MVC (3/16/2009)Monday, March 16, 2009 from Jared BarbozaSo lately I’ve been working on a project using Asp.net [...]

  2. DotNetShoutout Says:

    Testing JsonResult in Asp.net MVC « Code: Impossible…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  3. XYZ Says:

    Where is this Json(messageObj) comming from?

  4. Jared Says:

    @XYZ – The Index() action resides in a Asp.net MVC Controller which inherits from the controller base class. The controller base class has a Json() method which will return a JsonResult.

    Check out these links for more on JsonResult:
    http://nayyeri.net/using-jsonresult-in-asp-net-mvc-ajax
    http://msdn.microsoft.com/en-us/library/system.web.mvc.jsonresult.aspx
    http://trycatchfail.com/blog/post/2009/05/07/Simplified-unit-testing-for-ASPNET-MVC-JsonResult.aspx
    http://msdn.microsoft.com/en-us/library/system.web.mvc.controller_members.aspx

Leave a Reply


Page optimized by WP Minify WordPress Plugin