On Fri, 2024-08-02 at 21:37 +0100, Bilge wrote:
> Hi Ilija,
> I think this proposal has legs, and you are right to rekindle it,
> instead of letting it die quietly.
> On 02/08/2024 17:51, Ilija Tovilo wrote:
>  
> > * Some mocking libraries (e.g. Symfony's ClockMock [5])
> > intentionally
> > declare functions called from some file in the files namespace to
> > intercept these calls. This use-case would break. That said, it is
> > somewhat of a fragile approach to begin with, given that it
> > wouldn't
> > work for fully qualified calls, or unnamespaced code.
> > 
> My only concern is there needs to be an alternative way to do this:
> intercepting internal calls. Sometimes, whether due to poor
> architecture or otherwise, we just need to be able to replace an
> internal function call. One example I can think of recently is where
> I had to replace `header()` with a void function in tests, just to
> stop some legacy code emitting headers before the main framework
> kicked in, then unable to emit its own response because HTTP headers
> had already been sent. In a perfect world it shouldn't be necessary,
> but sometimes it is, so I think for this proposal to be palpable
> there must still be a way to achieve this.
> Cheers,
>  Bilge
>  


I was thinking about a similar problem this week.

If class A relies on class B, but you want to swap out
class B with a stub to test class A in isolation,
is there a way to make every call to class B,
from class A, actually call a different class
during the test, without modifying class A's code?


Minimal code for discussion purposes:


// conf class in global namespace
abstract class CONF {
   const DATABASE_HOST_NAME = 'db.example.com';
   const DATABASE_NAME = 'production';
   const DATABASE_USER_NAME = 'prod_user';
   const DATABASE_PASSWORD = '123';
}


// conf class in test namespace:
namespace test;
abstract class CONF {
   const DATABASE_HOST_NAME = 'db.sandbox.com';
   const DATABASE_NAME = 'test';
   const DATABASE_USER_NAME = 'test_user';
   const DATABASE_PASSWORD = 'abc';
}


// SQL class in global namespace
class SQL {

   private function Init(){
      self::$oPDO = new PDO(
         'mysql:host='.CONF::DATABASE_HOST_NAME.
         ';dbname='.CONF::DATABASE_NAME.';charset=utf8mb4',
         CONF::DATABASE_USER_NAME,
         CONF::DATABASE_PASSWORD,
         []
      );
   }
}

// Testing class in test namespace:
namespace test;
class SQLTester {

   // How do I make the SQL class see \test\CONF instead of
   // \CONF, when SQL calls for CONF in this test scope,
   /// without changing anything inside of the SQL class?
}


I think some kind of sandboxing tools would be useful for
build/test/deployment.

Reply via email to