I generally do something in between your DI and const-hack approach. Usually something like some sort of config class that can be asked for the payment provider. At least then your hack is not going to confuse people as much.
In this sort of situation I'd almost always be suspicious that there'll come a time when two payment providers are used in the system at once, or at least that switching to another one will happen. So I also try and reduce the number of references to the config thing, even if that's just through some factory type thing. Although clearly at this stage you're not going to know what will govern the choice between two payment providers, so it's not really possible to make it any cleaner. Not all "other programming (cough)" patterns are bad, although I'd say DI is less relevant (and frequently used in lieu of a proper solution). On Wed, Nov 14, 2012 at 10:56 AM, Steven Ringo <[email protected]>wrote: > We have a requirement to talk to a third party payment provider via an > http API > While I am happy with the testing of this implementation and mocking these > calls where necessary, I am looking for a good way to do this in the > development environment. > > The interactions with the provider have significant implications for the > UI that its unfeasible to test in an automated fashion. > > I don't want to use VCR or mock the web requests, as this is too low level > and the exact implementation has not been finalised. This doesn't mean the > UI can't be tweaked and tested though, and it would be good to have an > implementation that can be changed to emit the desired response by for > example, changing a flag. > > Here's where I am: > > I have a class that proxies calls from the app to the API, and in testing > its trivial to mock the calls to Acme.new > > class Acme > def pay_money(amount) > AcmeAPI::PayMoneyRequest.new({ > type: "Ca$h", > subscriber: @subscriber > amount: amount > }) > end > end > > class FakeAcme > def pay_money(amount) > canned_result = { invoice_number: "12345" } > end > end > > Assuming my app uses the Acme class as such: > > class PurchaseProduct > def buy_it_now > acme = Acme.new(subscriber) > result = acme.pay_money(product.price) > end > end > > If I want to replace Acme with FakeAcme, what is the best way to do this? > > In another programming (cough) life, I probably would have done something > like: > > class PurchaseProduct(acme_provider) > def buy_it_now > acme = acme_provider.new(subscriber) > result = acme.pay_money > end > end > > and then use some sort of DI library to specify the acme_provider at > runtime. > > I could do something like in the rails initializer to hack it too: > > if Rails.env.development? > Acme = FakeAcme > end > > Any comments/ideas on this approach or examples of alternatives would be > great. > > Thanks, > > Steve > > -- > You received this message because you are subscribed to the Google Groups > "Ruby or Rails Oceania" group. > To view this discussion on the web visit > https://groups.google.com/d/msg/rails-oceania/-/Vou8eHbj5SAJ. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/rails-oceania?hl=en. > -- You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.
