Using transaction object to test code in a multiple database persistence environment

An enterprise application of even a moderate size can quickly uses and updates several databases. I use here database in the "logical" sense of a stuff holding a state, not in the sense of an instance of an Oracle database or Sqlite or Zope or whatever. A database in this sense, can be a set of files in a directory, a message sent to a distant system, and of course your classical mysql or you-name-it instance.

The important word here is multiple. That is, you modify several of these data repository. Now how do you test ? How do you run your test code against this thing ?

  • Use only one database
  • You can't, example: billing
  • Use a transaction object

Example

Let's say you're writing the billing part of some system. Let's pretend that you gather data to know how much you've to bill, and let's further pretend that, once you know that, you will update the state in 4 "domains", each of them having its own persistence machinery:

  • The accounting database (accounting in the sense of the company, not the machine), so that people in the accounting department know from their computing system a bill has been sent to a certain customer for some amount; this is the accounting repository.
  • You store the PDF of the bill on some place, so the customer can get it, and may be some data so you know exactly what items where billed, and you can rebuild the bill if necessary; this is the billing repository.
  • You have a "not paid yet" database, so the customer management department can reminder the customer to pay if they have not. This is different from the accounting, because 1) theses are not the same people (accounting department vs customer department), so we assume they have different systems, and 2 when a reminder is sent, nothing has changed from the accounting point of view. This is also different from the billing repository, because the bill stays here for the eternity (this is not a "live" document), while the status of payment changes whenever a reminder is sent. Eventually, the customer will pay the bill and the due payment will be erased from the due payment system, while the bill will stay forever.
  • And finally, we send an email to the customer with the bill, which is not persistence per se, but is in the sense that you modify a state outside the scope of your program, and once it's done, it cannot be undone.

Starting code

Now what your code could looks like ? In arbitrary pseudo-code, it may looks something like this:

bill = gatherBill()
updateAccounting(bill)
updateBillRepository(bill)
updateCRM(bill)
sendEmail(bill)