Google Groups

Re: [silverstripe-dev] [GSOC 2012] Improve eCommerce and Payment modules

Frank Mullenger Mar 29, 2012 4:42 PM
Posted in group: SilverStripe Core Development
Thanks, sounds good. I guess I'll need to put aside half a day to read this thread on DI a bit more thoroughly:

So, just to clarify:
  1. The production service connects to gateway and processes payment as it would in a live environment
  2. The test service connects to gateway and processes payment for say a dev environment with test API account settings for the payment gateway - or manual testing
  3. Mock object represents the gateway and responds like the gateway would in order to run unit tests, it would not connect to the gateway it just mimics it.
I don't really understand the database backed mock gateway. When I think of manual testing I think of manually processing a payment for an order, in which case the test service (#2) would be used. Is it for creating payments to test managing them without requiring a test service or can we use fixtures/unit tests instead to test the same kind of things?

On Fri, Mar 30, 2012 at 11:49 AM, Sam Minnée <> wrote:

>> Mock requests / responses for testing sounds like a good start,
>> it might be nice to have the actual requests sent if test API keys
>> exist - depending on how hard it is to implement with the different
>> gateways.
> Perhaps create a static variable like PaymentTest::$make_external_calls,
> which determines whether to use external APIs or not. False by default.
> I could imagine it would be frustrating if you're developing/running tests
> without an internet connection.

The best way of doing this is to create a class that is a really, really thin layer around the payment gateway.  It might simply be the RestfulService class.  Perhaps it's assigned to $this->gateway inside the Payment class.  Then you have a setter, constructor argument, or Dependency Injection framework to specify what object should be provided to this gateway.  In different parts of your application you can then pass one of 3 implementations:

 1. The production service
 2. The test service (but still connecting to the
 3. A mock object that doesn't call anything

You don't necessarily need to have 3 separate classes - the first two might be the same class but with different properties.
If you like, you can use Phockito (or PHPUnit built-in mocking system, which I hate because of its verbosity) to create the 3rd one.  Or you can hand-roll a mock object that does what your tests need it to.

#1 would be used for production deployment
#2 would be used for manual test environments and possibly automated integration testing
#3 would be used for unit tests

You might have a 4th environment, that provides a database-backed mock gateway, where that database back-end is exposed in a modeladmin.  This would let you create a self-contained manual testing environment, but it means that you're testing more code that's not actually part of the production system, and it's more work.  It's arguable as to whether or not this is worthwhile.

The point is that by using this dependency injection (even without a DI framework this is still dependency injection) you don't need to bake any knowledge of this stuff into your Payment class.  It makes your code more testable, more maintainable, and more flexible.

You received this message because you are subscribed to the Google Groups "SilverStripe Core Development" group.
To post to this group, send email to
To unsubscribe from this group, send email to
For more options, visit this group at