June’s theme was “Testing things that are difficult to test”. The session started with a “Lightning talk” by @cyriux, describing several situations where testing can be quite complicated, as for instance :

Testing with large configuration problems: realistic search index, social algorithms, time series for financial analytics…

After this introduction, we were looking for a practical example of such a situation, and I suggested we could take a look at my implementation of this Linq provider. I haven’t gone very far yet, but my goal with this Linq to web service provider is to make the service return filtered data based on the Linq query. This means that I want the filtering to happen inside the web service, and not on the client side. And this is of course a behaviour that I want to test:

After some discussion, @cyriux pointed to me that there were several false assumptions in the way I was testing things. I assumed I would be testing the provider by using it against a service that I had built myself… but I had no need for an actual web service implementation ! The service and the provider are two separate features, and mustn’t be unit-tested at the same time.

I have not completely given up the idea of implementing the service, but it is now a separate objective that has nothing to do with the provider implementation. And the fact that the service is a web service is just an implementation detail. My vision of the way to organize the project is now the following :

The solution is now only composed of 3 assemblies :

PeopleFinder, which defines the service interface (i.e. the contract) and POCOs used as simple Data Transfer Objects,

LinqToService, which contains the actual implementation of the Linq provider,

UnitTests, which contains the tests and a “lambda-based” implementation of the PeopleFinder interface.

This organisation allows us to test only the behaviour of the provider, providing our own implementation of the service. To do so, we introduced a PeopleFinderLocator class. This might change in the future, but is quite out of scope here…

Given a query expression, the Linq provider’s goal is just to give the service the good parameters, and perform additional work that the service cannot handle. Here, the service knows how to filter the people based on their age. Let’s consider the following query :

When executing it, the provider must call the service with the appropriate parameter, and mustn’t do any additional work except handling the result back to the caller. The situation should be the following :

In the previous test, we use a LambdaBasedPeopleFinder implementation of the service, that actually filters some sample data based on a predicate. In some way we rely on this implementation because we test that the results are correctly filtered. But we can even test that the provider doesn’t do the service’s work !

If we adapt the previous test by replacing the lambda by p => true, the results returned by the service will not be filtered, and we can test that the provider correctly delegates the work to the service, and doesn’t filter the data.

Handle more complex queries, list all the type of nodes that can be found and handle them, ensuring the correctness of the returned data. If needed, any unhandled node type would result in using a blank SearchCriteria object and performing all the work using Linq to Objects,

Implement the service, even if it’s not necessary, just for the sake of it,