如何在 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()的区别

php get_called_class()函数与get_class函数的区别

get_class--返回对象的类名

如何获取对象的非限定(短)类名?

php中如何找到对象所属的类?