It’s easy to test LINQ queries when the LINQ queries always execute entirely in memory – like with LINQ to objects or LINQ to XML. All you need to do is put some in-memory data together and pass it to code executing the query.
It’s an entirely different scenario when you work with a remote LINQ provider (like NHibernate, Entity Framework, WCF Data Services, LINQ to Twitter, and all those types of technologies). Take the following simple query as an example.
var movies = _ctx.Movies .Where(movie => movie.Title.Contains("star")) .Take(1);
Let's imagine this query exists inside of a component (like an MVC controller). You want to unit test the query by giving the controller an in-memory fake for the database, while in production the code will execute against SQL Server.
What could possibly go wrong?
If you run the query against a SQL Server database full of movies you'll find a number of results, including "Star Wars" and "Starship Dave". In a unit test, let's imagine you've faked up some Movie data:
new Movie { ID=1, Title="Star Wars" }, // ...
Now hand the data off to a controller:
var controller = new HomeController(new FakeDbContext()); var result = controller.Index() as ViewResult; var model = result.ViewData.Model as IQueryable<Movie>; Assert.IsTrue(model.Any());
The unit test will never find Star Wars because String.Contains does a case and culture sensitive comparison. Most LINQ to SQL Server implementations will map Contains to the LIKE operator (WHERE [t].[title] LIKE N'%star%'), and LIKE will use the case sensitivity collation of SQL Server (which is case insensitive by default).
Not a huge problem, but if you are using "real" test data in-memory you'll see a difference in how the query behaves.
Another example is what happens if Title is nullable in the database. You might want to see what happens when you use nulls in your test data.
new Movie { ID=4, Title=null }
Now the query will work against SQL Server but the unit test will fail with a NullReferenceException. In-memory LINQ is trying to invoke the Contains method on a null string reference. But, the query works against SQL Server and the LIKE operator handles NULL values differently.
Not every LINQ provider supports every LINQ operator. For example, the following query will happily work in-memory, or with EF / LINQ to SQL.
var movies = ctx.Movies
.GroupBy(movie => movie.ReleaseDate.Year);
But, if you throw this query at WCF Data Services you'll get back a System.NotSupportedException {"The method 'GroupBy' is not supported."}.
It's also easy to break most LINQ providers by asking for something that only works in-memory.
var movies = _ctx.Movies .Where(movie => movie.Title.IndexOf('s') == 0);
With EF this generates a NotSupportedException: {"LINQ to Entities does not recognize the method 'Int32 IndexOf(Char)' method, and this method cannot be translated into a store expression."}
The goal of using test doubles and fakes is not to test your LINQ queries.
The goal is to test the objects and business logic consuming the results of the queries, and to do so without setting up and waiting for a real database.
As always, only integration tests will give you a total and complete assurance that your software will work 100% correctly in the real world*.
* Your mileage may vary.
The object initializer syntax introduced in C# makes it easy to work with "configuration" type objects.
public class TemperatureSetting { public float Value { get; set; } public float Variance { get; set; } public float Threshold { get; set; } } // ... var settings = new TemperatureSetting { Value = 104f, Variance = 0.6f, Threshold = 1.2f };
The code is easy to read, but, it becomes a bit trickier if you want some additional features from the class.
and
There are a few ways to solve the problem. One approach is to hide the property setters and provide a non-default constructor.
public class TemperatureSetting { public TemperatureSetting(float value, float variance, float threshold) { //... } public float Value { get; private set; } public float Variance { get; private set; } public float Threshold { get; private set; } }
However, this approach makes construction difficult to read, unless you define variables for each value to give them a name.
var settings = new TemperatureSetting(104f, 0.6f, 1.2f); // or var value = 104f; var variance = 0.6f; var threshhold = 1.2f; var settings = new TemperatureSetting(value, variance, threshhold);
Fortunately, C# 4.0 gives us named arguments - it's the best of both worlds.
var settings = new TemperatureSetting( value: 104f, variance: 0.6f, threshold: 1.2f );
All this code needs is an extra { and } and we can put a .js extension on the file …
We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely.
- from MF’s definition of POJO
The .NET equivalent to a POJO is a POCO (plain old CLR object). POCO is a popular term in .NET development today, having caught the momentum POJOs started generating 10 years ago. This isn’t because .NET is 10 years behind the curve. POJO developers were revolting against the tyranny of oppressive frameworks during a time when .NET developers were resetting from COM+ to managed code. The COM+ / WinDNA locomotive was headed in the same tyrannical direction when .NET derailed the train into relative simplicity.
But, I digress.
When I ask developers these days what POCO/POJO means to them I get consistent answers. Stuff like:
All these are good rules to define POCO. But why do these rules exist?
Java developers wanted POJOs because they wanted to own the code. The “plain” part is a side effect. They wanted to build object models without the restrictions imposed by a framework. They wanted the freedom to establish hierarchies and relationships. They wanted to pick the data types most suitable for a problem instead of using the data types required by infrastructure. I believe the true spirit of POJO/POCO-ness is only achieved when a developer cares deeply about the POCO classes. Like a gardener who cares about seedlings – the developer wants to grow the classes with a hands-on approach.
A generated POCO is an artifact a tool spits out after deriving information from another source - like a database schema. In most cases this is not a one time generation used to bootstrap a project. Instead, the code generator owns the POCO classes. Code generation dilutes the spirit of POCO.
Perhaps we need a new term: POGO – plain old generated object.
What do you think?
We've seen not one, but two posts this week where we used an ActionFilter as the solution to a problem. ActionFilters are powerful. ActionFilters can inspect and modify action parameters and action results. They can cover almost any cross-cutting concern in ASP.NET MVC: caching, security, auditing, etc.
But, should you use them everywhere?
[Log, UnitOfWork, PreParseParams] [CommonData, VerifyRedirects, HandleError] public class BusyController : Controller { }
Think about the other options:
HttpModules see the big picture. They can hook into the beginning of a request before a request even knows it's destined for a controller. Modules are configurable at runtime and can drop into any web site as a completely decoupled component (example: ELMAH).
Custom ModelBinders can build and tweak models, build action parameters, and provide some validation support. I'd use a model binder instead of an action filter if I wanted to change or inspect model or parameter values (see: tips for model binding).
Custom ActionResults can encapsulate what happens after an action finishes executing. Modify HTTP headers, set response properties, and more (example: custom ImageResult).
Don't default to using an ActionFilter if another solution is a better fit.
In the previous post we looked at using unit tests and reflection to ensure every controller derived from a specific base class in an ASP.NET MVC application. You might use a base class to ensure action filters are always in place for auditing, logging, or other general purpose security and runtime diagnostics.
You can also use action filters to inspect the result of a controller action. For example, you might want to check the Url of every RedirectResult to prevent open redirects in your application. Spammers love sites with open redirects.
Edit: thanks, Sergio for catching a copy/paste error (update to put the throw inside the if check). Sergio also pointed out the code allows redirects to non-HTTP URIs, and as shown doesn't allow a redirect to a local path (/home/index/123).
public class VerifyRedirects : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext filterContext) { var redirect = filterContext.Result as RedirectResult; if(redirect != null) { var host = new Uri(redirect.Url).Host; if(_whiteList.Any(host.EndsWith)) { return; } throw new InvalidOperationException(BadRedirectMessage); } } string[] _whiteList = { "microsoft.com", "odetocode.com", "pluralsight.com" }; const string BadRedirectMessage = "..."; }
In this case we are checking the URL against a white list of known destinations. If the host isn't found, the request stops with an exception.
In the previous post we talked about using a base controller class in ASP.NET MVC. The truly paranoid will worry about new developers on the team who don't know the rules and don't use the base class. One automated solution to this problem is to write a unit test to enforce the rule.
[TestMethod] public void AllControllersDeriveFromFootballController() { var badControllers = GetConcreteTypesAssignableTo<IController>() .Where(TypeIsNotDerivedFrom<FootballController>); if(badControllers.Any()) { var controllerNames = AggregateTypeNames(badControllers); Assert.Fail("Controllers are out of line: {0}", controllerNames); } }
The above code uses a few helper methods:
IEnumerable<Type> GetConcreteTypesAssignableTo<T>() { return Assembly .GetExecutingAssembly() .GetReferencedAssemblies() .Select(name => Assembly.Load(name.FullName)) .SelectMany(assembly => assembly.GetTypes()) .Where(type => typeof (T).IsAssignableFrom(type)) .Where(type => !type.IsAbstract); } bool TypeIsNotDerivedFrom<TBase>(Type type) { return !(typeof (TBase).IsAssignableFrom(type)); } string AggregateTypeNames(IEnumerable<Type> types) { return types .Select(type => type.Name) .Aggregate(new StringBuilder(), (sb, name) => sb.Append(name + " ")) .ToString(); }
Of course the test isn't so simple if controllers might use different base classes (think asynchronous controllers), and I'm sure some people question the value of a test like this in any case. Right?