6

TL;DR. Writing procedural code within a DB transaction. How can I improve design of the code so it's better testable?

In my application I have a service object that perform multiple things within the same transaction. See code in Ruby below:

class CreateRefundService
  def create(customer_id)
    ActiveRecord::Base.transaction do
      refund = create_refund(customer_id)
      credit = add_credits_to_customer(customer_id)

      send_email(refund)
      add_note(refund, credit)
    end
  end

  private

  # ... implementation of all 4 methods above
end

I'm trying to write 4 tests that would check that all four things happen during transaction, but it starts to feel uncomfortable, since for every method under test I need to stub other 3 methods. This gives me a warrant that there's probably a problem about this design.

I'm under constraints that multiple things need to happen during the same transaction.

1
5

The four methods seem to do things which make sense each on its own. So I would not see them as "implementation details which must kept private", I would see them as individual, reusable units, each unit worth to be tested on its own. So you can make them public and write a unit test directly for each.

What remains is to decide if you need some kind of automated integration test for the create method, or if you rely other tests on a different layer or level for this method.

1
  • Thanks, Doc. I went with adding a DSL class, CreateRefundDSL, which have all those methods as public. I have tested (pretty simple unit tests) them each one separately, and made this CreateRefundService depend on this new DSL class.
    – gmile
    Nov 30 '15 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.