custom software development to help your business take flight™

REST-like behavior with MVC instead of WCF

Posted by Joe Wilson on Sunday, March 7, 2010 6:16 PM

WCF is a very cool framework for adding an abstraction layer over your services.  You can have .asmx, .svc, and now, REST URLs with no extension.  These endpoints can even return JSON to the caller, which is useful if you’re using jQuery or another JavaScript library.

The knock on WCF?  The configuration story!  It’s getting better in WCF 4, which is scheduled for release in a month or so.  It will have a bunch of defaults so you don’t have to be as explicit in your config file.  Finally, some convention over configuration in the WCF space!  Now someone needs to create a fluent, code-based configuration tool for the exceptions to the default conventions…

Don’t be afraid of JSON!

Jason But if you need to return JSON to a caller today, you don’t need scary WCF config files to do it.  You can get the same URL and the same data payload with a lot less hassle using MVC controller actions.

The steps are:

  1. Create a new action in a controller.
  2. Grab your data or whatever you want to return.
  3. Parse your data to JSON.
  4. Throw it back out to the requestor.

The trick is to use JsonResult as the return type for your controller action and convert your output to a JSON string with the base controller’s Json method:

public JsonResult GetAllDepartments()
{
    var departments = _repository.GetAllDepartments();
    return Json(departments);
}

Now if I browse to this controller action (I’m using the HomeController in this example):

http://localhost/Home/GetAllDepartments

I get a pop-up to save the response stream, which I can open with Notepad:

[{"Name":"Human Resources"},{"Name":"Accounting"},{"Name":"IT"},{"Name":"Pencil Sharpening"}]

Yeah, JSON!  And there was no gory config setup needed!

Using jQuery with JSON

Now we can use jQuery in the MVC view to take advantage of this returned JSON. 

Here’s a view that has a button and a div tag.  jQuery is being used to tie the button click to a call to the controller and action we set up above.  It then gets the JSON coming back, loops through it, and puts it in the div tag so it’s visible to the user.

<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
    
<script type="text/javascript">
    $(function() {
        $("#btnShowDepartments").click(function() {
            $.getJSON("/Home/GetAllDepartments", null, function(data) {
                for (item in data) {
                    var department = data[item];
                    $("#divDepartments").append(department.Name, ", ");
                }
            });                
        });
    });        
</script>   

<p>
    <input id="btnShowDepartments" type="button" value="Show Departments" />
    <div id="divDepartments"></div>
</p>

This is probably not the best jQuery in the world.  I’m still new to it.  But the point is to show that you can put a URL in, parse the JSON, and use the data however your app needs it.

Tags: , , , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Increasing Testability

Posted by Joe Wilson on Sunday, March 7, 2010 4:30 PM

Testa-what?

I don't know if "testability" is a word, but if Bud Light can make up "drinkability", maybe it should be.  I'm talking about how pliant your code is to testing.  If you're doing TDD or BDD, the code you write is testable by definition. 

But if you're going the other way, and coding first or testing legacy code (any code not already under test), you've probably run into code that was hard to test and felt like giving up.  Some of the most common hurdles for testability are not coding to abstractions and not decoupling dependencies.  Here's how to get around that.

The problem

Here's a garden variety Order class with a ProcessOrder method:

public class Order
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Email { get; set; }
  public decimal Total { get; set; }

  public bool ProcessOrder()
  {
    var result = false;
      
    // Validate order
    if (!string.IsNullOrEmpty(this.Email) && this.Total > 0)
    {
      // Send order confirmation email
      var emailService = new EmailService();
      var emailSendResult = emailService.SendOrderConfirmationEmail(this);

      if (emailSendResult == true)
      {
        // Do more order processing...

        result = true;
      }
    }

    return result;
  }
}

And here's the test:

[Test]
public void Should_return_true_when_using_good_order_values()
{
  // Arrange
  var order = new Order();
  order.FirstName = "Joe";
  order.LastName = "Wilson";
  order.Email = "real_email_address@volaresystems.com";
  order.Total = 123.00m;

  // Act
  // Watch out!  Don't run this or it will send real emails!
  var result = order.ProcessOrder();

  // Assert
  Assert.That(result, Is.True);
}

We need to call the SendOrderConfirmationEmail method in the EmailService class.  But if our test calls ProcessOrder, there is no way to avoid calling the live emailing method as it's coded now.

How can we test the logic in the ProcessOrder method without sending out a real email?

Code to Abstractions

First, we need to code to an abstraction of EmailService, not to the concrete class itself.  So let's create an interface around EmailService:

public interface IEmailService
{
    bool SendOrderConfirmationEmail(Order order);
}

Then change the EmailService class to implement this new interface.  Visual Studio 2008 and ReSharper make this easy. 

This will let us change our test later to use a fake version of IEmailService instead of the real one.

Decouple and Invert your Dependencies

The next problem is we're creating an instance of the EmailService class in the ProcessOrder method.  Anytime you use "new" in your code, you're probably introducing a dependency and reducing testability. 

The fix is to let the caller create the instance and tell the class or method being called which instance to use.  I am using a private field with constructor injection to set the field instance.  Note we're also now coding to the interface IEmailService instead of the instance EmailService.

Here's the full Order method using the private field to call the SendOrderConfirmationEmail method on IEmailService inside the ProcessOrder method.

public class Order
{
  private readonly IEmailService _emailService;

  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Email { get; set; }
  public decimal Total { get; set; }

  public Order(IEmailService emailService)
  {
      _emailService = emailService;
  }

  public bool ProcessOrder()
  {
    var result = false;
      
    // Validate order
    if (!string.IsNullOrEmpty(this.Email) && this.Total > 0)
    {
      // Send order confirmation email
      //var emailService = new EmailService(); // Created outside this class now
      var emailSendResult = _emailService.SendOrderConfirmationEmail(this);

      if (emailSendResult == true)
      {
        // Do more order processing...

        result = true;
      }
    }

    return result;
  }
}

Dependencies can be very hard to spot, but it's critical to tease them out of your code to increase testability.  They can even come from things as innocuous as DateTime.  If you're code relies on DateTime.Now, how will you write unit tests for your logic without changing your system clock when you run the test?  It's simpler to have the caller pass in the DateTime value and have the method do the calculations based on whatever value it is given.

Make a Fake

Now that we've got testable code, we can make a fake EmailService and update our test.

First, create the FakeEmailService class implementing the IEmailService we created earlier.  We need the SendOrderConfirmationEmail method to return true to simulate an email being successfully sent.

public class FakeEmailService : IEmailService
{
  public bool SendOrderConfirmationEmail(Order order)
  {
    return true;
  }
}

You could also use a mocking framework like Moq or Rhino Mocks for this, but a homemade fake is easy, too.

Now we're ready to update our test to use the fake and inject it into the Order constructor:

[Test]
public void Should_return_true_when_using_good_order_values()
{
    // Arrange
    var emailService = new FakeEmailService();
    order = new Order(emailService);
    order.FirstName = "Joe";
    order.LastName = "Wilson";
    order.Email = "real_email_address@volaresystems.com";
    order.Total = 123.00m;

    // Act
    var result = order.ProcessOrder();

    // Assert
    Assert.That(result, Is.True);
}

Last step

We've refactored the Order class so the caller sends the IEmailService instance to it.  That makes sense for the test, but what about the real code?

I typically use an IOC container like Structure Map or Castle Windsor to hold and resolve an in-memory dictionary of interfaces and class instances.  You wire it up at application startup and when you call something that needs IEmailService, it creates an instance of EmailService for you.

If you're working with legacy code and can't use and IOC container, you also can add a no arg constructor like this:

public Order() : this(new EmailService())
{
}

public Order(IEmailService emailService)
{
    _emailService = emailService;
}

Your legacy code keeps calling the no arg constructor like it used to, and any new code and your test code use the constructor with IEmailService dependency passed in.

Wrap up

If you code isn't testable, you won't test it.  If you're working with legacy code or writing tests after coding, you can use these techniques to pull out external dependencies so they can be faked for testing. 

You can have it all: testable code, unit tests around that code, and no broken legacy code.  Mmmm.Testability.Drink it in!

Tags: , ,
Categories: Technical


kick it on DotNetKicks.com shout it on DotNetShoutOut

Image Details