我有以下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
有没有办法可以从等式检查中排除某些属性?
答案 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);
}
}
}