phpunit 测试方法,调用其他需要 mock 的类方法

2022-08-30 16:08:16

我试图创建一个非常标准的单元测试,我调用一个方法并断言它的响应,但是我正在测试的方法在同一类中调用另一个方法,这有点繁重的工作。

我想模拟一个方法,但仍然按原样执行我正在测试的方法,仅使用从对另一个方法的调用返回的模拟值。

我已经把这个例子弄得一团糟,让它变得尽可能简单。

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;

    }

}

我尝试编写测试。

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);

    }

}

我尝试过模拟MyClass对象,但是当我这样做并调用testMethod时,它总是返回null。我需要一种方法来模拟一种方法,但保持对象的其余部分不变。


答案 1

可以模拟正在测试的类,并指定要模拟的方法。

$mock = $this->getMockBuilder('MyClass')
    ->setMethods(array('handleValue'))
    ->getMock();

$mock->expects($this->once())
    ->method('handleValue')
    ->will($this->returnValue(23)) //Whatever value you want to return

但是,IMO这不是您测试的最佳主意。像这样的测试将使重构变得更加困难。您指定的是类的实现,而不是类应该具有的行为。如果正在做很多复杂的工作,使测试变得困难,请考虑将逻辑移动到一个单独的类中,并将其注入到你的类中。然后,您可以创建该类的模拟并将其传递给 。这样做将为您提供额外的优势,即如果需要调整其行为,则可以使其更具可扩展性。handleValuetestMethodMyClasshandleValue

http://www.oodesign.com/strategy-pattern.html

作为一般规则,您不应模拟正在测试的系统。


答案 2

您可以使用指定要模拟(部分模拟)的方法: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');

未在您给出的数组中指定的类中的任何其他方法将按原样执行。如果不使用,所有方法都将返回,除非您专门设置它们。setMethods()setMethodsNULL


推荐