我正在尝试创建一个非常标准的单元测试,我调用一个方法并断言它的响应,但是我正在测试的方法在同一个类中调用另一个方法,它会做一些繁重的工作.
我想模拟那个方法,但仍然执行我正在测试的方法,只有通过调用另一个方法返回的模拟值.
我愚弄了这个例子,让它变得尽可能简单.
class MyClass
{
// I want to test this method, but mock the handleValue method to always return a set value.
public function testMethod($arg)
{
$value = $arg->getValue();
$this->handleValue($value);
}
// This method needs to be mocked to always return a set value.
public function handleValue($value)
{
// Do a bunch of stuff...
$value += 20;
return $value;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试写测试.
class MyClassTest extends \PHPUnit_Framework_TestCase
{
public function testTheTestMethod()
{
// mock the object that is passed in as an arg
$arg = $this->getMockBuilder('SomeEntity')->getMock();
$arg->expects($this->any())
->method('getValue')
->will($this->returnValue(10));
// test handle document()
$myClass = new MyClass();
$result = $myClass->testMethod($arg);
// assert result is the correct
$this->assertEquals($result, 50);
}
}
Run Code Online (Sandbox Code Playgroud)
我试过模拟MyClass对象,但是当我这样做并调用testMethod时它总是返回null.我需要一种方法来模拟一个方法,但保留对象的其余部分.
Sch*_*eis 24
您可以模拟正在测试的类,并指定要模拟的方法.
$mock = $this->getMockBuilder('MyClass')
->setMethods(array('handleValue'))
->getMock();
$mock->expects($this->once())
->method('handleValue')
->will($this->returnValue(23)) //Whatever value you want to return
Run Code Online (Sandbox Code Playgroud)
但是,IMO这不是您测试的最佳选择. 像这样的测试会使重构变得更加困难.您正在指定类的实现,而不是该类应具有的行为.如果handleValue
做了很多使测试变得困难的复杂工作,可以考虑将逻辑移到一个单独的类中并将其注入到类中.然后你可以创建该类的模拟并将其传递给testMethod
.MyClass
如果handleValue
需要调整其行为,这样做将为您提供额外的优势,使其更具可扩展性.
http://www.oodesign.com/strategy-pattern.html
作为一般规则,您不应该模拟您正在测试的系统.
gre*_*reg 11
您可以使用以下命令指定要模拟(部分模拟)的方法setMethods()
:
// Let's do a `partial mock` of the object. By passing in an array of methods to `setMethods`
// we are telling PHPUnit to only mock the methods we specify, in this case `handleValue()`.
$csc = $this->getMockBuilder('Lightmaker\CloudSearchBundle\Controller\CloudSearchController')
->setConstructorArgs($constructor)
->setMethods(array('handleValue'))
->getMock();
// Tell the `handleValue` method to return 'bla'
$csc->expects($this->any())
->method('handleValue')
->with('bla');
Run Code Online (Sandbox Code Playgroud)
在您给出的数组中未指定的类中的任何其他方法setMethods()
将按原样执行.如果您不使用setMethods
所有方法将返回,NULL
除非您专门设置它们.