PHPUnit 中的模拟与存根
Mocks vs Stubs in PHPUnit
我知道存根验证状态而模拟验证行为。
如何在 PHPUnit 中创建模拟来验证方法的行为? PHPUnit 没有验证方法 (verify()),而且我不知道如何在 PHPUnit.
中进行模拟
在文档中,对创建存根有很好的解释:
// Create a stub for the SomeClass class.
$stub = $this->createMock(SomeClass::class);
// Configure the stub.
$stub
->method('doSomething')
->willReturn('foo');
// Calling $stub->doSomething() will now return 'foo'.
$this->assertEquals('foo', $stub->doSomething());
但在这种情况下,我正在验证状态,说 return 一个答案。
如何创建模拟和验证行为的示例?
PHPUnit 过去支持两种开箱即用的创建测试替身的方法。除了遗留的 PHPUnit 模拟框架,我们还可以选择 prophecy。
预言支持已在 PHPUnit 9 中删除,但可以通过安装 phpspec/prophecy-phpunit
.
重新添加
PHPUnit 模拟框架
createMock
方法用于创建三个最知名的测试替身。这是您配置对象的方式,使它成为虚拟对象、存根或模拟对象。
您还可以使用模拟生成器(getMockBuilder
returns 模拟生成器)创建测试存根。这只是做同样事情的另一种方式,让您可以通过流畅的界面调整一些额外的模拟选项(更多信息请参见 the documentation)。
虚拟
Dummy 被传递,但从未真正被调用,或者如果它被调用,它会以默认答案响应(主要是 null
)。它的存在主要是为了满足参数列表。
$dummy = $this->createMock(SomeClass::class);
// SUT - System Under Test
$sut->action($dummy);
存根
存根与类似查询的方法一起使用 - return 的方法,但它们是否被实际调用并不重要。
$stub = $this->createMock(SomeClass::class);
$stub->method('getSomething')
->willReturn('foo');
$sut->action($stub);
模拟
Mocks 与类似命令的方法一起使用 - 调用它们很重要,我们不太关心它们的 return 值(命令方法通常不会 return 任何值).
$mock = $this->createMock(SomeClass::class);
$mock->expects($this->once())
->method('doSomething')
->with('bar');
$sut->action($mock);
在您的测试方法执行完毕后,预期会自动得到验证。在上面的示例中,如果方法 doSomething
未在 SomeClass
上调用,或者使用与您配置的参数不同的参数调用它,测试将失败。
间谍
不支持。
预言
Prophecy 现在由 PHPUnit 开箱即用地支持,因此您可以使用它作为遗留模拟框架的替代品。同样,这是您配置对象的方式使它成为特定类型的测试替身。
虚拟
$dummy = $this->prophesize(SomeClass::class);
$sut->action($dummy->reveal());
存根
$stub = $this->prophesize(SomeClass::class);
$stub->getSomething()->willReturn('foo');
$sut->action($stub->reveal());
模拟
$mock = $this->prophesize(SomeClass::class);
$mock->doSomething('bar')->shouldBeCalled();
$sut->action($mock->reveal());
间谍
$spy = $this->prophesize(SomeClass::class);
// execute the action on system under test
$sut->action($spy->reveal());
// verify expectations after
$spy->doSomething('bar')->shouldHaveBeenCalled();
傻瓜
首先,看假人。一个虚拟对象既是我的样子,如果你让我记住我把车钥匙放在哪里......也是你得到的对象,如果你在 phpspec 中添加一个带有类型提示的参数来获得测试替身......然后绝对不对它做任何事情。因此,如果我们得到一个测试替身并且不添加任何行为并且不对其方法进行任何断言,它就称为 "dummy object".
哦,在他们的文档中,您会看到 $prophecy->reveal() 之类的内容。这是一个我们不需要担心的细节,因为 phpspec 会为我们处理好。得分!
存根
只要您开始控制甚至一种方法的一个 return 值……砰!这个对象突然被称为存根。来自文档:"a stub is an object double" - 所有这些东西都被称为测试替身或对象替身 - 当放在特定环境中时,它们会以特定方式表现。这是一种奇特的说法:只要我们添加其中一个 willReturn() 东西,它就会变成一个存根。
实际上,大部分文档都在讨论存根和准确控制其行为方式的不同方法,包括我们之前看到的参数通配符。
模拟
如果你继续往下读,接下来你会发现 "mocks"。当你调用 shouldBeCalled() 时,一个对象变成了一个 mock。因此,如果您想添加一个方法被调用一定次数的断言,并且您想将该断言放在实际代码之前 - 使用 shouldBeCalledTimes() 或 shouldBeCalled() - 恭喜!您的对象现在称为模拟。
间谍
最后,在底部,我们有间谍。间谍与模拟完全相同,只是当您在代码后添加期望时 - 就像 shouldHaveBeenCalledTimes().
https://symfonycasts.com/screencast/phpspec/doubles-dummies-mocks-spies
我知道存根验证状态而模拟验证行为。
如何在 PHPUnit 中创建模拟来验证方法的行为? PHPUnit 没有验证方法 (verify()),而且我不知道如何在 PHPUnit.
中进行模拟在文档中,对创建存根有很好的解释:
// Create a stub for the SomeClass class.
$stub = $this->createMock(SomeClass::class);
// Configure the stub.
$stub
->method('doSomething')
->willReturn('foo');
// Calling $stub->doSomething() will now return 'foo'.
$this->assertEquals('foo', $stub->doSomething());
但在这种情况下,我正在验证状态,说 return 一个答案。
如何创建模拟和验证行为的示例?
PHPUnit 过去支持两种开箱即用的创建测试替身的方法。除了遗留的 PHPUnit 模拟框架,我们还可以选择 prophecy。
预言支持已在 PHPUnit 9 中删除,但可以通过安装 phpspec/prophecy-phpunit
.
PHPUnit 模拟框架
createMock
方法用于创建三个最知名的测试替身。这是您配置对象的方式,使它成为虚拟对象、存根或模拟对象。
您还可以使用模拟生成器(getMockBuilder
returns 模拟生成器)创建测试存根。这只是做同样事情的另一种方式,让您可以通过流畅的界面调整一些额外的模拟选项(更多信息请参见 the documentation)。
虚拟
Dummy 被传递,但从未真正被调用,或者如果它被调用,它会以默认答案响应(主要是 null
)。它的存在主要是为了满足参数列表。
$dummy = $this->createMock(SomeClass::class);
// SUT - System Under Test
$sut->action($dummy);
存根
存根与类似查询的方法一起使用 - return 的方法,但它们是否被实际调用并不重要。
$stub = $this->createMock(SomeClass::class);
$stub->method('getSomething')
->willReturn('foo');
$sut->action($stub);
模拟
Mocks 与类似命令的方法一起使用 - 调用它们很重要,我们不太关心它们的 return 值(命令方法通常不会 return 任何值).
$mock = $this->createMock(SomeClass::class);
$mock->expects($this->once())
->method('doSomething')
->with('bar');
$sut->action($mock);
在您的测试方法执行完毕后,预期会自动得到验证。在上面的示例中,如果方法 doSomething
未在 SomeClass
上调用,或者使用与您配置的参数不同的参数调用它,测试将失败。
间谍
不支持。
预言
Prophecy 现在由 PHPUnit 开箱即用地支持,因此您可以使用它作为遗留模拟框架的替代品。同样,这是您配置对象的方式使它成为特定类型的测试替身。
虚拟
$dummy = $this->prophesize(SomeClass::class);
$sut->action($dummy->reveal());
存根
$stub = $this->prophesize(SomeClass::class);
$stub->getSomething()->willReturn('foo');
$sut->action($stub->reveal());
模拟
$mock = $this->prophesize(SomeClass::class);
$mock->doSomething('bar')->shouldBeCalled();
$sut->action($mock->reveal());
间谍
$spy = $this->prophesize(SomeClass::class);
// execute the action on system under test
$sut->action($spy->reveal());
// verify expectations after
$spy->doSomething('bar')->shouldHaveBeenCalled();
傻瓜
首先,看假人。一个虚拟对象既是我的样子,如果你让我记住我把车钥匙放在哪里......也是你得到的对象,如果你在 phpspec 中添加一个带有类型提示的参数来获得测试替身......然后绝对不对它做任何事情。因此,如果我们得到一个测试替身并且不添加任何行为并且不对其方法进行任何断言,它就称为 "dummy object".
哦,在他们的文档中,您会看到 $prophecy->reveal() 之类的内容。这是一个我们不需要担心的细节,因为 phpspec 会为我们处理好。得分!
存根
只要您开始控制甚至一种方法的一个 return 值……砰!这个对象突然被称为存根。来自文档:"a stub is an object double" - 所有这些东西都被称为测试替身或对象替身 - 当放在特定环境中时,它们会以特定方式表现。这是一种奇特的说法:只要我们添加其中一个 willReturn() 东西,它就会变成一个存根。
实际上,大部分文档都在讨论存根和准确控制其行为方式的不同方法,包括我们之前看到的参数通配符。
模拟
如果你继续往下读,接下来你会发现 "mocks"。当你调用 shouldBeCalled() 时,一个对象变成了一个 mock。因此,如果您想添加一个方法被调用一定次数的断言,并且您想将该断言放在实际代码之前 - 使用 shouldBeCalledTimes() 或 shouldBeCalled() - 恭喜!您的对象现在称为模拟。
间谍
最后,在底部,我们有间谍。间谍与模拟完全相同,只是当您在代码后添加期望时 - 就像 shouldHaveBeenCalledTimes().
https://symfonycasts.com/screencast/phpspec/doubles-dummies-mocks-spies