PHPUnit mock返回值和使用同一类中不同方法的特定参数调用的次数

PHPUnit mock返回值和使用同一类中不同方法的特定参数调用的次数,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,我的场景类似于以下内容: class ToMock { public function iReturn() { return time(); } public function callMe1($arg1, $arg2) { return true; } public function callMe2($arg1, $arg2) { return true; } } cl

我的场景类似于以下内容:

class ToMock
{
    public function iReturn()
    {
        return time();
    }

    public function callMe1($arg1, $arg2)
    {
        return true;
    }

    public function callMe2($arg1, $arg2)
    {
        return true;
    }
}

class ToTest
{
    public function feedMe(ToMock $toMock)
    {
        if ($toMock->iReturn() > 100) {
            $toMock->callMe1(5, 10);
        }

        if ($toMock->iReturn() < 200) {
            $toMock->callMe2(15, 20);
        }
    }
}
class-ToMock
{
公共职能
{
返回时间();
}
公共函数callMe1($arg1,$arg2)
{
返回true;
}
公共函数callMe2($arg1,$arg2)
{
返回true;
}
}
等级测试
{
公共功能feedMe(ToMock$ToMock)
{
如果($toMock->iReturn()>100){
$toMock->callMe1(5,10);
}
如果($toMock->iReturn()<200){
$toMock->callMe2(15,20);
}
}
}
现在,我想测试
ToMock::iReturn()
是否返回150,
ToTest::feedMe()
调用
ToMock::callMe1()
一次5和10,以及
ToMock::callMe2()
一次15和20


我知道我可以模拟
ToMock::iReturn
返回150,也可以模拟
ToMock
使用提供的参数期望一个特定的方法。但是,有可能同时完成所有这些工作吗?如果是,它会是什么样子?

如果我正确理解了您的问题,那么测试代码会是什么样子

class MockingExpectationsTest extends PHPUnit_Framework_TestCase
{
    private $obj;
    private $mock;

    public function setUp(){
        $this->mock = $this->createMock(ToMock::class);
        $this->obj = new ToTest();
    }

    public function testExpectations(){
        $this->mock->expects($this->exactly(2))
                   ->method('iReturn')
                   ->willReturn(150);
        $this->mock->expects($this->exactly(1))
                   ->method('callMe1')
                    ->with(5, 10);
        $this->mock->expects($this->exactly(1))
                   ->method('callMe2')
                    ->with(15, 20);
        $this->obj->feedMe($this->mock);
    }
}

如果我正确理解了您的问题,那么测试代码可能如下所示

class MockingExpectationsTest extends PHPUnit_Framework_TestCase
{
    private $obj;
    private $mock;

    public function setUp(){
        $this->mock = $this->createMock(ToMock::class);
        $this->obj = new ToTest();
    }

    public function testExpectations(){
        $this->mock->expects($this->exactly(2))
                   ->method('iReturn')
                   ->willReturn(150);
        $this->mock->expects($this->exactly(1))
                   ->method('callMe1')
                    ->with(5, 10);
        $this->mock->expects($this->exactly(1))
                   ->method('callMe2')
                    ->with(15, 20);
        $this->obj->feedMe($this->mock);
    }
}
是的

下面是一个测试示例,涵盖了
ToTest

<?php

use PHPUnit\Framework\TestCase;

class ToTestTest extends TestCase
{
    /**
     * @dataProvider providerTimeBetween0And100
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsBetween0And100($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->never())
            ->method('callMe1');

        $toMock
            ->expects($this->once())
            ->method('callMe2')
            ->with(
                $this->identicalTo(15),
                $this->identicalTo(20)
            );

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeBetween0And100()
    {
        return $this->providerTimeBetween(0, 100);
    }

    /**
     * @dataProvider providerTimeBetween101And199
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsBetween101And199($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->once())
            ->method('callMe1')
            ->with(
                $this->identicalTo(5),
                $this->identicalTo(10)
            );

        $toMock
            ->expects($this->once())
            ->method('callMe2')
            ->with(
                $this->identicalTo(15),
                $this->identicalTo(20)
            );

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeBetween101And199()
    {
        return $this->providerTimeBetween(101, 199);
    }
    /**
     * @dataProvider providerTimeGreaterThan199
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsGreaterThan199($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->once())
            ->method('callMe1')
            ->with(
                $this->identicalTo(5),
                $this->identicalTo(10)
            );

        $toMock
            ->expects($this->never())
            ->method('callMe2');

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeGreaterThan199()
    {
        return $this->providerTimeBetween(200, 300);
    }

    private function providerTimeBetween($min, $max)
    {
        for ($time = $min; $time < $max; ++$time) {
            yield [
                $time
            ];
        }
    }
}
是的,是的

下面是一个测试示例,涵盖了
ToTest

<?php

use PHPUnit\Framework\TestCase;

class ToTestTest extends TestCase
{
    /**
     * @dataProvider providerTimeBetween0And100
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsBetween0And100($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->never())
            ->method('callMe1');

        $toMock
            ->expects($this->once())
            ->method('callMe2')
            ->with(
                $this->identicalTo(15),
                $this->identicalTo(20)
            );

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeBetween0And100()
    {
        return $this->providerTimeBetween(0, 100);
    }

    /**
     * @dataProvider providerTimeBetween101And199
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsBetween101And199($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->once())
            ->method('callMe1')
            ->with(
                $this->identicalTo(5),
                $this->identicalTo(10)
            );

        $toMock
            ->expects($this->once())
            ->method('callMe2')
            ->with(
                $this->identicalTo(15),
                $this->identicalTo(20)
            );

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeBetween101And199()
    {
        return $this->providerTimeBetween(101, 199);
    }
    /**
     * @dataProvider providerTimeGreaterThan199
     *
     * @param int $time
     */
    public function testFeedMeWhenTimeIsGreaterThan199($time)
    {
        $toMock = $this->createMock(ToMock::class);

        $toMock
            ->expects($this->exactly(2))
            ->method('iReturn')
            ->willReturn($time);

        $toMock
            ->expects($this->once())
            ->method('callMe1')
            ->with(
                $this->identicalTo(5),
                $this->identicalTo(10)
            );

        $toMock
            ->expects($this->never())
            ->method('callMe2');

        $toTest = new ToTest();

        $toTest->feedMe($toMock);
    }

    public function providerTimeGreaterThan199()
    {
        return $this->providerTimeBetween(200, 300);
    }

    private function providerTimeBetween($min, $max)
    {
        for ($time = $min; $time < $max; ++$time) {
            yield [
                $time
            ];
        }
    }
}