Pages

Friday, June 28, 2013

Great New Feature of F# 3.1 (CRUD applications rejoice)

I was pretty disappointed when I asked on stackoverflow how I could easily compose predicates in F# (because this is so easy in C# with LINQ)

Thomas Petricek gave me a thorough and clear answer and it's really impressive that the entire language is quotable.

http://stackoverflow.com/questions/13826749/how-do-you-compose-query-expressions-in-f

The only problem is that this code is really hard for a beginner to write; so you're still probably going to be using the query computation expression for your SQL/ORM/type provider queries as a beginner.

So here's what you'll be writing ( source : http://msdn.microsoft.com/en-us/library/vstudio/hh225374.aspx )

query {
    for number in data do
    skipWhile (number < 3)
    select student
    }

To me, this is the second coming of SQL and LINQ/fluent style is preferred.  Composability and modularity are completely lost on this style unless you do some quoting/splicing.  I was really disappointed that the normal way to query in F# was so weak, and the best way was a bit too complicated with a lot of upfront thinking required.  

Up until today, C# provided a more flexible way of accessing external data. Even if they had to add many language features to make this happen, easier to use is still easier to use.

Well, today they announced F# 3.1 which will provide real support for using LINQ-style extension methods.  Anyone making CRUD applications should seriously consider giving F# a try now.


Friday, June 21, 2013

Beginning ASP.NET MVC dependency injection and automated testing

Let's take a look at testing the simplest MVC controller that could prove the worth of automated testing/dependency injection.

Our task is the following:
  •  For users configured to view English webpages, output "Hello World!" 
  •  For Users configured to view Spanish webpages, output "Hola Mundo!"
  • For users configured to view any other language, throw an exception.
We will prove our application performs this way via automated tests.

The way we know a user's language preference is via the 'Accept-language' header in an HTTP request.


Getting this information out of the request is simple.  Anywhere in your code you can write the following to get a user's most preferred language :


BUT you have to be sure that HttpContext has its properties set (its properties are set in thread local storage by ASP.NET, for those wondering).  In other words, this will only work when executing as part of a web request.

This poses a problem for unit testing.  When you write a test like this:

It will throw an exception when it tries executing your controller's action because the test runner isn't running your code with a set HttpContext.

Dependency Injection

The best way to make our class testable is to use dependency injection.  

We're going to setup our controller to get the preferred language from a class that implements IRequest, an interface that looks like this


And we'll implement it using the one liner for preferred language like we did above 


The major difference to the code we are trying to to test will be that we going to have our controller rely on the IRequest interface as opposed to using the HttpContext class directly. Our class will look like this :


Now, all we need to test our controller is a stub of IRequest that will allow us to specify the incoming language.


This now allows us to write three comprehensive tests where we can actually specify the language ourselves and prove the behavior of our controllers even though we aren't actually receiving an HTTP request.

In production : [Inject]

For this to work in production, you may have noticed in the HomeController class I'm using an 'Inject' attribute which will eventually resolve to an instance of  the 'Request' class when the code is serving a real HTTP request.

How does this work?

I'm using a third party library called Ninject (the MVC 3 package) that lets me easily specify these bindings for the production run of the app.  Meaning, that after HomeController gets allocated, the IRequest will automatically be set to my Request concrete class.

Obviously this mapping must be done to ensure that when my code is running as an MVC application, and not in unit tests, that its using the class that utilizes the real HttpContext.

Conclusion

What we have accomplished

  • Wrote a controller that only depends on an interface, not a built-in ASP.NET class that only works inside an HTTP request.
  • Proved our controller works for three different language scenarios (would be quite a pain to have to change your browsers language setting to test each scenario).
  • Can see that dependency injection is useful for unit testing classes that have external dependencies.  Other external dependencies include : file systems, databases, and web services. 
  • Used Ninject to make property injection as painless as possible in production.