Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

When we use test double feature, we mock services and pretend like we call them. When we don't use test double feature, we don't mock services and call them directly. In the case of test double, the example below would not make sense because if you break tested classes, your test testGetUsersWithMock() would still pass because the it is not actually calling the tested classes. I am just showing you how both options can be used.


ParameterUtil


namespace Application\Util;

class ParameterUtil
{
const MIN_PAGE = 0;
const MAX_LIMIT = 5;
const MIN_LIMIT = 1;

public function getPage($page)
{
if (!$page || $page < 1) {
$page = self::MIN_PAGE;
}

return (int) $page;
}

public function getLimit($limit)
{
if (!$limit || $limit < 1) {
$limit = self::MIN_LIMIT;
} elseif ($limit > self::MAX_LIMIT) {
$limit = self::MAX_LIMIT;
}

return (int) $limit;
}
}

UserService


namespace Application\Service;

use Application\Util\ParameterUtil;

class UserService
{
const USERS = [
'User 1',
'User 2',
'User 3',
'User 4',
'User 5',
'User 6',
'User 7',
'User 8',
'User 9',
'User 10',
];

private $parameterUtil;

public function __construct(ParameterUtil $parameterUtil)
{
$this->parameterUtil = $parameterUtil;
}

public function get($page = null, $limit = null)
{
$page = $this->parameterUtil->getPage($page);
$limit = $this->parameterUtil->getLimit($limit);

return array_slice(self::USERS, $page, $limit);
}
}

UserServiceTest


namespace tests\Application\Service;

use Application\Service\UserService;
use Application\Util\ParameterUtil;
use PHPUnit\Framework\TestCase;

class UserServiceTest extends TestCase
{
/** @var ParameterUtil */
private $parameterUtil;

protected function setUp()
{
$this->parameterUtil = new ParameterUtil();
}

protected function tearDown()
{
$this->parameterUtil = null;
}

/**
* @dataProvider getUsersDataProvider
*/
public function testGetUsers($page, $limit, $expected)
{
$userService = new UserService($this->parameterUtil);

$result = $userService->get($page, $limit);

$this->assertEquals($expected, $result);
}

/**
* @dataProvider getUsersDataProvider
*/
public function testGetUsersWithMock($page, $limit, $expected)
{
$userService = $this->getMockBuilder(UserService::class)
->setConstructorArgs([$this->parameterUtil])
->getMock();

$userService->expects($this->any())
->method('get')
->will($this->returnValue($expected));

$this->assertEquals($expected, $userService->get($page, $limit));
}

public function getUsersDataProvider()
{
return [
[null, null, ['User 1']],
[1, null, ['User 2']],
[null, 1, ['User 1']],
[1, 1, ['User 2']],
[2, 1, ['User 3']],
[2, 2, ['User 3', 'User 4']],
];
}
}

Test


$ vendor/bin/phpunit
PHPUnit 5.7.22 by Sebastian Bergmann and contributors.

............ 12 / 12 (100%)

Time: 23 ms, Memory: 3.75MB

OK (12 tests, 12 assertions)