I @Vadym Ansatz und aktualisiert es implementiert haben. Jetzt benutze ich es zum Testen erfolgreich!
protected function getFinalMock($originalObject)
{
if (gettype($originalObject) !== 'object') {
throw new \Exception('Argument must be an object');
}
$allOriginalMethods = get_class_methods($originalObject);
// some "unmockable" methods will be skipped
$skipMethods = [
'__construct',
'staticProxyConstructor',
'__get',
'__set',
'__isset',
'__unset',
'__clone',
'__sleep',
'__wakeup',
'setProxyInitializer',
'getProxyInitializer',
'initializeProxy',
'isProxyInitialized',
'getWrappedValueHolderValue',
'create',
];
// list of all methods of Query object
$originalMethods = [];
foreach ($allOriginalMethods as $method) {
if (!in_array($method, $skipMethods)) {
$originalMethods[] = $method;
}
}
$reflection = new \ReflectionClass($originalObject);
$parentClass = $reflection->getParentClass()->name;
// Very dummy mock
$mock = $this
->getMockBuilder($parentClass)
->disableOriginalConstructor()
->setMethods($originalMethods)
->getMock();
foreach ($originalMethods as $method) {
// skip "unmockable"
if (in_array($method, $skipMethods)) {
continue;
}
// make proxy call to rest of the methods
$mock
->expects($this->any())
->method($method)
->will($this->returnCallback(
function (...$args) use ($originalObject, $method, $mock) {
$ret = call_user_func_array([$originalObject, $method], $args);
// mocking "return $this;" from inside $originalQuery
if (is_object($ret) && get_class($ret) == get_class($originalObject)) {
if (spl_object_hash($originalObject) == spl_object_hash($ret)) {
return $mock;
}
throw new \Exception(
sprintf(
'Object [%s] of class [%s] returned clone of itself from method [%s]. Not supported.',
spl_object_hash($originalObject),
get_class($originalObject),
$method
)
);
}
return $ret;
}
));
}
return $mock;
}
Sie können eine Kopie der FINAL Klasse erstellen, die nicht endgültig ist und verspotten es –
@BryantFrankford Dank für die Lösung . Während dies funktionieren würde, würde ich es am liebsten vermeiden, eine neue Klasse für diese spezielle Situation zu schreiben. Sie würden sich nicht einer Lösung bewusst sein, die ein wenig besser skalieren würde? Wenn dies zu meinem Projekt wird, dann werde ich die obige Lösung implementieren – DanHabib
Anders als die ursprüngliche Klasse zu ändern, um nicht endgültig zu sein, habe ich persönlich keine andere Lösung. –