PHPUnit:获取equalTo断言以忽略属性

Xat*_*too 2 php phpunit

我有以下PHPUnit测试用例:

    $mailer = $this->getMockBuilder(MailerInterface::class)->getMock();
    $simpleMailer = new SimpleMailer($mailer);

    $message = (new Message())
        ->setTo($user)
        ->setFrom($from)
        ->setSubject($subject)
        ->setTemplate(SimpleMailer::TEMPLATE)
        ->setContext(['message' => $body]);

    if ($bcc) { $message->addBcc($bcc); }

    $mailer
        ->expects($this->once())
        ->method('send')
        ->with($this->equalTo($message));

    $simpleMailer->sendMessage($user, $subject, $body, $from, $bcc);
Run Code Online (Sandbox Code Playgroud)

在更改Message类之前,此方法一直工作良好。Message类现在在构造上设置一个唯一的ID,这意味着它equalTo现在返回false,具有以下区别:

 MailerBundle\Document\Message Object (
-    'id' => '5a372f3c-a8a9-4e1e-913f-d756244c8e52'
+    'id' => '11176427-7d74-4a3c-8708-0026ae666f8b'
     'type' => null
     'user' => Tests\TestUser Object (...)
     'toName' => ''
     'toAddress' => null
     'domain' => null
     'fromName' => null
     'fromAddress' => 'user@example.org'
     'bccAddresses' => Array (...)
     'subject' => 'subject'
     'textBody' => null
     'htmlBody' => null
     'template' => 'MailerBundle:MailTemplates:...l.twig'
     'context' => Array (...)
)
Run Code Online (Sandbox Code Playgroud)

有什么方法可以从相等性检查中排除某些属性?

Ale*_*lex 5

如果您的Message类具有吸气剂,则可以在with函数中使用回调以仅匹配您关心的属性。类似于

$mailer
    ->expects($this->once())
    ->method('send')
    ->with($this->callback(function(Message $message) use ($user, $from, $subject, $body) {
            return $message->getTo() == $user 
                && $message->getFrom() == $from 
                && $message->getSubject() == $subject 
                && $message->getTemplate() == SimpleMailer::TEMPLATE
                && $message->getContext()['message'] == $body
        }));
Run Code Online (Sandbox Code Playgroud)


Chr*_*uhn 2

Sebastian 在https://github.com/sebastianbergmann/phpunit/issues/4034中建议使用自定义比较器的另一个解决方案

我的用例是在测试主题被反序列化(serialize())后断言对象相等:自定义 __serialize() 在执行此操作时会忽略一些属性,因此使用自定义比较器来忽略这些属性。

final class FooTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        // Register custom comparator to compare IncludeTree with its unserialize(serialize())
        // representation since we don't serialize all properties. Custom comparators are
        // unregistered after test by phpunit runBare() automatically.
        $this->registerComparator(new UnserializedIncludeTreeObjectComparator());
    }

    /**
     * @test
     */
    public function foo(): void
    {
        $includeTree = [...]
        self::assertEquals($includeTree, unserialize(serialize($includeTree)));
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这个比较器类:

final class UnserializedIncludeTreeObjectComparator extends ObjectComparator
{
    protected function toArray($object): array
    {
        $arrayRepresentation = parent::toArray($object);
        if ($object instanceof IncludeInterface) {
            // This property is not serialized and falls back to default
            // value on unserialize(). We ignore it for equality comparison.
            unset($arrayRepresentation['name']);
        }
        return $arrayRepresentation;
    }
}
Run Code Online (Sandbox Code Playgroud)