The tests that come to your mind, when all you have are messages

The majority of the developers do the enterprise related development. Probably, you’re one of them. Even if pet projects or OSS contributions are important to you, enterprise related development is the thing you spend with majority of your professional time. Enterprise applications are quite dependent. You don’t have just a database and an app sitting on top of it. There are many services, applications, databases that your solution need to talk to. Additionally, the communication may be very different, from REST services using http to TCP, queues, or even shared databases… The question which arises is are the true unit tests the tests that you should use to cover your whole application? How do you test at all an application which is in the worst case just a mediator?

How would you describe the API provided by your service, the database, queues etc? Follow my way of thinking and consider them as output-input. In the center there’s your application configured with a fancy DI container, properly configured. Consider now calling an API to get a current account state. Your application access the database to get cached glossaries to provide properly named properties, gets some data from external transactional service, possibly sends a notification with some queue. Now, let turn these into named entities:

  • GetAccountsData (call to your API)
    • FetchGlossaries (call to your DB)
    • GetAccounts (call to transactional system)
    • NotifyCompliance (push to queue)

How would you test this flow? Using strict mocks, some substitutions? I’d say, instead of interfaces, services repositories go with a simple approach of messages and handlers. The whole flow is a result of initial message GetAccountsData. Having provided responses to FetchGlossaries, GetAccounts, NotifyCompliance in a simple form: just take the request object and compare it serialized version with the one registered as fake. If that fits, return the preregistered response. At the end you should assert the result of GetAccountsData.

To minimize the set of faked responses, fail the test if the response was not used at all. Fail if it was used to many times if you want. You may go into world of mocking libraries, but it’s not needed when every call is a simple single object passed to a mediator, dispatching it to a handler. You know the thing about objects. You easily deep compare them with a simple serialization output.

Is it a test? Yes. Is it a unit test? Not at all. You’re asserting the whole configured system. Is it worth? In my opinion with that approach you can have more business oriented tests, describing some scenarios rather than tests handling external mock/assert libraries. If I would this approach everywhere? Probably not. With a highly collaborative and dependent applications it seems to me know as a time and sanity saver. Define input-output and assert the system as a whole. Nothing more, nothing less.

Features and unit tests

Currently I’m involved in a greenfield project, which was happy enough to start as a event-sourced DDD. The paradigm fits well the domain, but there is some cost of zero-iteration which is being paid now. The cost is a small infrastructure which has to be provided to be wrap the domain. It’s really small (maybe not that small), but has to be tested. To make it simple/complex I’d add that it consists of a few functionalities/modules, each providing and consuming some contracts. So what about testing?

Recently I re-read a Kozmic’s blog entry, which covers a very interesting problem of unit tests vs ‘real life scenarios’ as well as ‘Concepts and features’ written by Ayende. It made me think a lot about the new application and the way I tried to test it. I took the first module, which had a small test base written in a not-good-as-it-should-be manner, deleted the tests and started to implemented sth new.

I know that some people have opinion ‘no container in your tests’, but in tests of the infrastructure? Come on, this is all about matching all the pieces of the code you wrote! Nevertheless, having the WindsorInstaller of a specific part of the application I initialized the container, added one stub for the external dependencies and fully configured this part of the application. All the tests used the enpoints provided by the whole functionality and it worked like a charm. It seems that the number of test fixtures will be equal to the number of functionalities/modules the infrastructure provide. I find it a quick, simple and powerful solution for having it testes. What about the unit tests? If I have some infrastructure class longer than 100 lines and plenty of methods in there, I will go for unit tests, but for now, this paradigm works like a charm.