如何模拟 PHP 中通过 get_class 检查的对象?
How do I mock an object in PHP that passes get_class inspection?
我已经遇到了 this 线程,但我的用例略有不同,因为我没有创建要测试的服务的新实例,而是从容器。我的问题是如何找到该切换案例逻辑中的特定案例?
实施:
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);
}
简而言之,如果您正在使用 createMock
,您将无法使用 get_class
。模拟返回 extend class 提供的而不是直接实现它,并且对 class 名称进行直接字符串比较是行不通的。
根据您的消息的复杂程度 class,或者如果您无法修改您的服务,您可能需要考虑改用固定装置。也就是说,只调用 $message = new MyFirstClass()
而不是模拟它。您认为消息是服务的依赖项,还是只是一个待处理的对象?对于第二种情况,夹具可能更有意义。在 Martin Fowler 的网站上有一些关于此的更详细的讨论,此处:https://martinfowler.com/articles/mocksArentStubs.html
或者,如果您可以修改服务,那么您就可以使用 instanceof
,因为它可以与 subclasses 一起使用。
而不是
switch (get_class($message)) {
case MyFirstClass::class:
...
会是
if ($message instanceof MyFirstClass::class) {
...
我已经遇到了 this 线程,但我的用例略有不同,因为我没有创建要测试的服务的新实例,而是从容器。我的问题是如何找到该切换案例逻辑中的特定案例?
实施:
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);
}
简而言之,如果您正在使用 createMock
,您将无法使用 get_class
。模拟返回 extend class 提供的而不是直接实现它,并且对 class 名称进行直接字符串比较是行不通的。
根据您的消息的复杂程度 class,或者如果您无法修改您的服务,您可能需要考虑改用固定装置。也就是说,只调用 $message = new MyFirstClass()
而不是模拟它。您认为消息是服务的依赖项,还是只是一个待处理的对象?对于第二种情况,夹具可能更有意义。在 Martin Fowler 的网站上有一些关于此的更详细的讨论,此处:https://martinfowler.com/articles/mocksArentStubs.html
或者,如果您可以修改服务,那么您就可以使用 instanceof
,因为它可以与 subclasses 一起使用。
而不是
switch (get_class($message)) {
case MyFirstClass::class:
...
会是
if ($message instanceof MyFirstClass::class) {
...