PHPUnit 模拟使用模拟
PHPUnit mock using mock
我有两个 class,我想通过 PHPUnit 测试它。
但是我在嘲笑这些东西时做错了。我想改变第一个 class 调用的方法。
class One {
private $someVar = null;
private $abc = null;
public function Start() {
if ( null == $this->someVar) {
$abc = (bool)$this->Helper();
}
return $abc;
}
public function Helper() {
return new Two();
}
}
Class Two {
public function Check($whateverwhynot) {
return 1;
}
}
Class testOne extends PHPUnit_Framework_TestCase {
public function testStart() {
$mockedService = $this
->getMockBuilder(
'Two',
array('Check')
)
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder(
'One',
array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
}
而 $result
的结果是 NULL
,而不是 'true
'
如果我不使用断言行,我会收到一条错误消息:
F
Time: 0 seconds, Memory: 13.00Mb
There was 1 failure:
1) testOne::testStart
Expectation failed for method name is equal to <string:Check> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
想法?
更新
- 环境:PHP 5.4.3x,PHPUnit 3.7.19
- 一个重要的事情:不能修改原来的classes(Class一个和Class两个)
您可以使用来自 ouzo-goodies 的模拟。
类:
class One
{
private $someVar = null;
private $abc = null;
private $two;
public function __construct(Two $two)
{
$this->two = $two;
}
public function Start()
{
if (null == $this->someVar) {
$abc = (bool)$this->Helper()->Check(1213);
}
return $abc;
}
public function Helper()
{
return $this->two;
}
}
在构造函数中注入对象Two
,这样你就可以很容易地模拟这个对象。
class Two
{
public function Check($whateverwhynot)
{
return 1;
}
}
并测试:
class OneTest extends PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function shouldCheckStart()
{
//given
$mock = Mock::create('\Two');
Mock::when($mock)->Check(Mock::any())->thenReturn(true);
$one = new One($mock);
//when
$start = $one->Start();
//then
$this->assertTrue($start);
}
}
mocks 的文档。
你创建的模拟是错误的。您正在使用 $this->getMockBuilder()
,它只接受一个参数,即要模拟的 class 的名称。您似乎将它与需要多个 $this->getMock()
混为一谈。
将测试更改为:
public function testStart() {
$mockedService = $this
->getMockBuilder('Two')
->setMethods(array('Check'))
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder('One')
->setMethods(array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
这不是一个好的测试,因为我们需要模拟我们正在测试的 class,但您声明您根本无法更改 classes。
我有两个 class,我想通过 PHPUnit 测试它。 但是我在嘲笑这些东西时做错了。我想改变第一个 class 调用的方法。
class One {
private $someVar = null;
private $abc = null;
public function Start() {
if ( null == $this->someVar) {
$abc = (bool)$this->Helper();
}
return $abc;
}
public function Helper() {
return new Two();
}
}
Class Two {
public function Check($whateverwhynot) {
return 1;
}
}
Class testOne extends PHPUnit_Framework_TestCase {
public function testStart() {
$mockedService = $this
->getMockBuilder(
'Two',
array('Check')
)
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder(
'One',
array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
}
而 $result
的结果是 NULL
,而不是 'true
'
如果我不使用断言行,我会收到一条错误消息:
F
Time: 0 seconds, Memory: 13.00Mb
There was 1 failure:
1) testOne::testStart
Expectation failed for method name is equal to <string:Check> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
想法?
更新 - 环境:PHP 5.4.3x,PHPUnit 3.7.19 - 一个重要的事情:不能修改原来的classes(Class一个和Class两个)
您可以使用来自 ouzo-goodies 的模拟。
类:
class One
{
private $someVar = null;
private $abc = null;
private $two;
public function __construct(Two $two)
{
$this->two = $two;
}
public function Start()
{
if (null == $this->someVar) {
$abc = (bool)$this->Helper()->Check(1213);
}
return $abc;
}
public function Helper()
{
return $this->two;
}
}
在构造函数中注入对象Two
,这样你就可以很容易地模拟这个对象。
class Two
{
public function Check($whateverwhynot)
{
return 1;
}
}
并测试:
class OneTest extends PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function shouldCheckStart()
{
//given
$mock = Mock::create('\Two');
Mock::when($mock)->Check(Mock::any())->thenReturn(true);
$one = new One($mock);
//when
$start = $one->Start();
//then
$this->assertTrue($start);
}
}
mocks 的文档。
你创建的模拟是错误的。您正在使用 $this->getMockBuilder()
,它只接受一个参数,即要模拟的 class 的名称。您似乎将它与需要多个 $this->getMock()
混为一谈。
将测试更改为:
public function testStart() {
$mockedService = $this
->getMockBuilder('Two')
->setMethods(array('Check'))
->getMock();
$mockedService
->expects($this->once())
->method('Check')
->with('13')
->will($this->returnValue(true));
$mock = $this
->getMockBuilder('One')
->setMethods(array('Helper'))
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('Helper')
->will($this->returnValue($mockedService));
$result = $mock->Start();
$this->assertFalse($result);
}
这不是一个好的测试,因为我们需要模拟我们正在测试的 class,但您声明您根本无法更改 classes。