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.