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

时间:2017-04-24 13:32:44

标签: php phpunit

我有以下PHPUnit测试用例:

import static org.junit.Assert.assertEquals;
import org.junit.Test;

import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;

public class MockSubClassTest {


@Test
public void mockSuperClassTest(@Mocked final SuperClass superClass){

    new MockUp<Util>() {
        @Mock
        public String getAppName(){
            return "FXI";
        }
    };



    SubClass subClass = new SubClass("data"); 
    assertEquals("data", subClass.getData());

    assertEquals("FXI", subClass.getApp());

}
}

public class SubClass extends SuperClass {

String data;

public SubClass(String string) {
    super(string);
    data = string;
}

public String getData() {
    return data;

}

}


public class SuperClass {

public final static String app = Util.getAppName();

public SuperClass(String data) {
    throw new IllegalArgumentException();
}


public String getApp(){
    return app;
}
}

public class Util {

public static TestObject getObject() {
    // TODO Auto-generated method stub
    return null;
}

public static String getAppName() {
    // TODO Auto-generated method stub
    return null;
}

这一点工作正常,直到Message类被更改。 Message类现在在构造时设置唯一ID,这意味着 $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); 现在返回false,但有以下区别:

equalTo

有没有办法可以从等式检查中排除某些属性?

4 个答案:

答案 0 :(得分:4)

如果您的Message类具有getter,则可以使用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
        }));

答案 1 :(得分:2)

我刚刚写了类似的文章,并且好奇是否重新发明了轮子(我几乎做了)。但是,我想在这里分享我的结果,以防万一,因为它与您的用例(如我的)相匹配。

我的目标是比较两个对象并断言属性之间是否相等,并能够忽略指定的键。我正在当前的PHPunit(2020年2月)中使用它。

private function assertEqualWithIgnore($expected, $actual, $ignoreKeys = [], $currentKey = null): void
    {
        if (is_object($expected)) {
            foreach ($expected as $key => $value) {
                $this->assertEqualWithIgnore($expected->$key, $actual->$key, $ignoreKeys, $key);
            }
        } elseif (is_array($expected)) {
            foreach ($expected as $key => $value) {
                $this->assertEqualWithIgnore($expected[$key], $actual[$key], $ignoreKeys, $key);
            }
        } elseif ($currentKey !== null && !in_array($currentKey, $ignoreKeys)) {
            $this->assertEquals($expected, $actual);
        }
    }

答案 2 :(得分:1)

你必须确保它是平等的对象吗?如果不是,我会建议使用匹配器,例如

->with($this->isInstanceOf(Message::class))

您还可以使用以下方法组合多项检查: logicalAnd()

以下是可用匹配器的良好资源:http://archive.gregk.me/2011/phpunit-with-method-argument-matchers/

答案 3 :(得分:1)

受布赖恩(Brian)的回答启发,这是一个帮助程序,用于在进行相等检查之前修剪不需要的ID。这样,行为仍然非常接近phpunit的assertEquals。

您一次获得所有属性的相等性检查,而不是一次。您还可以更轻松地发现检查失败的地方。

private function assertEqualsButIgnore($expected, $actual, $ignoreKeys = []): void
{
    $copyExpected = $expected;
    $this->recursiveUnset($copyExpected, $ignoreKeys);

    $copyActual = $actual;
    $this->recursiveUnset($copyActual, $ignoreKeys);

    $this->assertEquals($copyExpected, $copyActual);
}

private function recursiveUnset(&$objOrArray, $unwanted_key): void
{
    foreach($unwanted_key as $key) {
        if(is_array($objOrArray)) {
            unset($objOrArray[$key]);
        } else {
            unset($objOrArray->$key);
        }
    }
    foreach ($objOrArray as &$value) {
        if (is_array($value) || is_object(($value))) {
            $this->recursiveUnset($value, $unwanted_key);
        }
    }
}