如何在 PHP 中模拟通过 get_class 检查的对象?
Posted
技术标签:
【中文标题】如何在 PHP 中模拟通过 get_class 检查的对象?【英文标题】:How do I mock an object in PHP that passes get_class inspection? 【发布时间】:2021-10-20 02:24:28 【问题描述】:我已经遇到过this 线程,但我的用例略有不同,因为我没有创建要测试的服务的新实例,而是从容器中获取实例及其所有依赖项。我的问题是如何在那个 switch-case 逻辑中找到一个特定的案例?
实现:
interface MessageInterface * my code *
class MyFirstClass extends Message * my code *
class MySecondClass extends Message * my code *
class MyThirdClass extends Message * my code *
abstract class Message implements MessageInterface * my code *
public function sendMessage(MessageInterface $message) : void
var_dump(get_class($message));
// output: "Mock_MyFirstClass_c5f215a6"
var_dump( MyFirstClass::class);
// output: "My\Namespace\MyFirstClass"
switch (get_class($message))
case MyFirstClass::class:
**how to get here?**
$message->render();
break;
case MySecondClass::class:
break;
case MyThirdClass::class:
break;
测试:
public function setUp() : void
parent::setUp();
$this->myService = $this->container->getMyService();
public function testSendMessage() : void
$message = $this->createMock(MyFirstClass::class);
$message->expects($this->once())->method("render");
$this->myService->sendMessage($message);
【问题讨论】:
【参考方案1】:简而言之,如果您使用createMock
,您将无法使用get_class
。模拟返回 extend 提供的类而不是直接实现它,并且对类名进行直接字符串比较是行不通的。
根据消息类的复杂性,或者如果您无法修改服务,您可能需要考虑使用固定装置。也就是说,只需调用$message = new MyFirstClass()
而不是嘲笑它。您认为消息是服务的依赖,还是只是要处理的对象?对于第二种情况,固定装置可能更有意义。在 Martin Fowler 的网站上有一些更详细的讨论,这里是:https://martinfowler.com/articles/mocksArentStubs.html
或者,如果您可以修改服务,那么您将能够改用instanceof
,因为它适用于子类。
而不是
switch (get_class($message))
case MyFirstClass::class:
...
应该是
if ($message instanceof MyFirstClass::class)
...
【讨论】:
以上是关于如何在 PHP 中模拟通过 get_class 检查的对象?的主要内容,如果未能解决你的问题,请参考以下文章
PHP的继承方法如何获取子类名?get_class() 和 get_called_class
php __CLASS__get_class()与get_called_class()的区别