Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying CQRS - Is unit testing the thin read layer necessary?

Given that some of the advice for implementing CQRS advocates fairly close-to-the-metal query implementation, such as ADO.NET queries directly against the database (or perhaps a LINQ-based ORM), is it a mistake to try and unit test them?

I wonder if it's really even necessary?

My thoughts on the matter:

  1. The additional architectural complexity to provide a mockable "Thin Read Layer" seems opposite to the very nature of the advice to keep the architectural ceremony to a minimum.
  2. The number of unit tests to effectively cover every angle of query that a user might compose is horrendous.

Specifically I'm trying CQRS out in an ASP.NET MVC application and am wondering whether to bother unit testing my controller action methods, or just test the Domain Model instead.

Many thanks in advance.

like image 866
Neil Barnwell Avatar asked Feb 02 '11 00:02

Neil Barnwell


People also ask

When should you use CQRS?

When to use CQRS pattern. Consider CQRS for the following scenarios: Collaborative domains where many users access the same data in parallel. CQRS allows you to define commands with enough granularity to minimize merge conflicts at the domain level, and conflicts that do arise can be merged by the command.

Should I test repository layer?

Yes, you should test your repository layer. Although the majority of these tests fall into a different classification of tests. I usually refer to them as integration tests to distinguish them from my unit tests.

What testing method would you use to test a 3rd party application?

If you want to test the interaction with the 3rd party or with the file system, then what you need is integration testing which means that you test all the parts that have already been unit tested and assert how they work together.


4 Answers

In my experience 90%-99% of the reads you will be doing if you are creating a nice de-normalized read model DO NOT warrant having unit tests around them.

I have found that the most effective and efficient way to TDD a CQRS application is to write integration tests that push commands into your domain, then use the Queries to get the data back out of the DB for your assertions.

like image 192
pjbss Avatar answered Sep 20 '22 21:09

pjbss


I would tend to agree with you that unit testing this kind of code is not so beneficial. But there is still some scope for some useful tests.

You must be performing some validation of the user's read query parameters, if so, then test that invalid request parameters throw a suitable exception, and valid parameters are allowed.

If you're using an ORM, I find the cost/benefit ratio too great for testing the mapping code. Assume your ORM is already tested, there could be errors in the mapping, but you'll soon find and fix them.

I also find it useful to write some Integration tests (using the same Testing framework), just to be sure I can make a connection to the database, and the ORM configuration doesn't throw any mapping exceptions. You certainly don't want to be writing unit tests that query the actual db.

like image 38
Andronicus Avatar answered Sep 17 '22 21:09

Andronicus


As you probably already know unit testing is less about code coverage and preventing bugs than it is about good design. While I often skip testing the read-model event handlers when I'm in a hurry, there can be no doubt that it probably should be done for all the reasons code should be TDD'd.

I also have not be unit testing my HTTP actions (I don't have controllers per se since I'm using Nancy not .NET MVC).

These are integration points and don't tend to contain much logic since most of it is encapsulated in the command handlers and domain model.

The reason I think it is fairly easy not to test these is because they are very simple and very repetitive, there is almost no deep thinking in the denormalization of events to the read-model. The same is true for my HTTP handlers, which pretty much just process the request and issue a command to the domain, with some basic logic for return a response to the client.

When developing, I often make mistakes in this code and I probably would make far fewer of these mistakes if I was using TDD, but it would also take much longer and these mistakes tend to be very easy to spot and fix.

My gut tells me I should still apply TDD here though, it is still all very loosely coupled and it shouldn't be hard to write the tests. If you are finding it hard to write the tests that could indicate a code smell in your controllers.

like image 34
Chris Nicola Avatar answered Sep 16 '22 21:09

Chris Nicola


The way that I have seen something like this unit tested is to have the unit test create a set of things in the database, you run your unit tests, then clean out the created things.

In one past job I saw this set up very nicely using a data structure to describe the objects and their relationships. This was run through the ORM to create those objects, with those relationships, data from that was used for the queries, and then the ORM was used to delete the objects. To make unit tests easier to set up every class specified default values to use in unit tests that didn't override those values. Then the data structure in the unit tests only needed to specify non-default values, which made the setup of the unit tests much more compact.

These unit tests were very useful, and caught a number of bugs in the database interaction.

like image 34
btilly Avatar answered Sep 18 '22 21:09

btilly