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.

oldhomemovie
  • 171
  • 5
  • related (possibly a duplicate): [Staying OO and Testable while working with a database](http://programmers.stackexchange.com/questions/42792/staying-oo-and-testable-while-working-with-a-database) – gnat Nov 27 '15 at 21:06

1 Answers1

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.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • 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. – oldhomemovie Nov 30 '15 at 16:43