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.