Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing PHPUnit方法调用期望与断言_Unit Testing_Phpunit_Mockery - Fatal编程技术网

Unit testing PHPUnit方法调用期望与断言

Unit testing PHPUnit方法调用期望与断言,unit-testing,phpunit,mockery,Unit Testing,Phpunit,Mockery,创建mock类通常涉及在mock/testdouble上配置方法调用期望 例如,在“香草”PHPUnit中,我们可以存根一个方法调用并设置如下期望: $stub->expects($this->any())->method('doSomething')->willReturn('foo') 在模拟对象框架中,我们得到如下API: $mock->shouldReceive('doIt')->with(m::anyOf('this','that'))->andReturn($this->getSom

创建mock类通常涉及在mock/testdouble上配置方法调用期望

例如,在“香草”PHPUnit中,我们可以存根一个方法调用并设置如下期望:

$stub->expects($this->any())->method('doSomething')->willReturn('foo')

在模拟对象框架中,我们得到如下API:

$mock->shouldReceive('doIt')->with(m::anyOf('this','that'))->andReturn($this->getSomething())

像这样的期望通常是在测试套件的设置阶段实现的,例如
\PHPUnit\u Framework\u TestCase
setUp()
方法

像上面提到的那些期望,如果没有实现,将打破测试。因此,将期望变成实际的断言

这导致了这样一种情况,即我们的断言(断言+期望)分散在测试用例类中,因为我们在测试用例的设置阶段以及在单个测试中都有实际的断言

在“常规的”
assert..
method中测试方法调用期望是否是一种好的做法。这可能看起来像(嘲弄):

然后在其中一种试验方法的末尾:

public function testSoemthing()
{ 
    ...
    $this->assertMethodCalled($this->mock, 'setSomeValue');
}
assertMethodCalled
,不是PHPUnit公开的方法。它必须得到实施


简言之,我们是否应该将期望声明视为实际的断言,然后在我们的测试方法中对它们进行测试?

您不需要在
setUp()
方法中配置测试双精度(存根/模拟)

实际上,我永远不会在测试设置代码中配置模拟,我只会在其中放置非常常见的存根。对于每个测试用例,模拟期望通常是不同的。我宁愿在设置代码中实例化我的双重测试,将它们分配给私有属性,并在每个测试用例中配置它们

private$注册;
私人储存库;
受保护的函数设置()
{
$this->repository=$this->getMock(UserRepository::class);
$this->registration=新注册($repository);
}
公共函数testUserIsAddedToTheRepositoryDuringRegistration()期间
{
$user=$this->createUser();
$this->repository
->预期($this->once())
->方法('add')
->使用($用户);
$this->registration->register($user);
}
因此,在测试用例中放置测试双重配置是很好的。它实际上更好,因为您的测试用例具有所有上下文,因此更具可读性。如果您发现自己配置了大量的测试用例或编写了很长的测试用例,这可能意味着您有太多的协作者,您应该考虑如何改进您的设计。您还可以使用具有有意义名称的帮助器方法来提高测试用例的可读性,即
$this->givenExistingUser()
$this->givenRepositoryWithNoUsers()

正如您所注意到的,模拟期望(不要将它们与不是期望的存根混淆)与断言非常接近。实际上,有一种方法可以通过另一种类型的测试替身——间谍来完成你想要的任务

间谍不受经典phpunit模拟框架的支持。然而,PHPUnit现在有一个内置的预言支持。幸运的是,预言。下面是一个例子:

private$注册;
私人储存库;
受保护的函数设置()
{
$this->repository=$this->size(UserRepository::class);
$this->registration=新注册($repository->leaver());
}
公共函数testUserIsAddedToTheRepositoryDuringRegistration()期间
{
$user=$this->createUser();
$this->registration->register($user);
$this->repository->add($user)->shoulldhavebeencalled();
}
最后,我在同一个测试用例中避免断言和模拟期望。大多数情况下,这些是单独的行为,应该用不同的测试用例来覆盖


要了解更多关于双打测试的信息,请阅读精彩推荐。

谢谢您的宝贵建议。我还发现mockry的
MockInterface
还公开了一个方法
shouldlhavebeencalled()
,因此它可以像您在Prophecy中所展示的那样使用。另外,将预期的方法调用与其他行为分开测试确实会更好。总之,我认为可以肯定地说,
shouldlhavebeencalled()
是一个成熟的断言,需要自己的测试用例。
public function testSoemthing()
{ 
    ...
    $this->assertMethodCalled($this->mock, 'setSomeValue');
}