Как создать mock разных методов одного класса и как создать mock одного метода с разными аргументами

Jul 02, 2013 11:57

Как создать mock разных методов одного класса и как создать mock метода с разными аргументами. Используем стандартный PHPUnit.

Моки в PHPUnit создаются методом getMock(). Этот метод принадлежит классу PHPUnit_Framework_TestCase, который описан в файле .../PEAR/PHPUnit/Framework/TestCase.php
Спецификация метода PHPUnit_Framework_TestCase::getMock()

/**
* Returns a mock object for the specified class.
* @param string $originalClassName
* @param array $methods
* @param array $arguments
* @param string $mockClassName
* @param boolean $callOriginalConstructor
* @param boolean $callOriginalClone
* @param boolean $callAutoload
* @param boolean $cloneArguments
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getMock(
$originalClassName,
$methods = array(),
array $arguments = array(),
$mockClassName = '',
$callOriginalConstructor = TRUE,
$callOriginalClone = TRUE,
$callAutoload = TRUE,
$cloneArguments = FALSE)

1. Моки разных методов одного класса.
Например у нас есть некоторый класс MyClass с методом root(), вычисляющим корень n-ой степени, который нужно тестировать. Степень корня берется из метода getRootBase(), а точность задается в конфигурации и берется из метода getConfig('presision').
Таким образом у нас есть два метода: getRootBase() и getConfig('presision') для которых нужны моки.

class MyClass
{
function root($x)
{
$base = $this->getRootBase();
$presision = $this->getConfig('presision');
$root = pow($x, 1/$base);
return round($root, $presision);
}

protected function getConfig($key)
{
$aConfig['presision'] = 2;
return $aConfig[$key];
}

protected function getRootBase()
{
return 3;
}
}

Тестируем метод root() с помощью двух моков для двух необходимых методов.

class MyClassTest extends PHPUnit_Framework_TestCase
{
function testroot()
{
$mockMy = $this->getMock('\MyClass', array('getConfig', 'getRootBase'));

$mockMy->expects($this->any())
->method('getConfig')
->with('presision')
->will($this->returnValue(2));

$mockMy->expects($this->any())
->method('getRootBase')
->will($this->returnValue(2));

$this->assertEquals(2.83, $mockMy->root(8));
}
}

2. Мок одного метода с разными аргументами.
Например у нас есть метод умножения которому нужен тип и модификатор из конфигурации. Таким образом, чтобы протестировать метод multi() потребуется мок для getConfig(), который будет возвращать различные значения в зависимости от своего аргумента. Для этого в моке используем метод returnCallback(), который будет анализировать аргумент и возвращать нужное значение.

class MyClass
{
function multi($a, $b)
{
$type = $this->getConfig('multitype');
$result = 0;
switch($type)
{
case 'strong':
$modificator = $this->getConfig('multimodificator');
$result = $a*$b*$modificator;
break;
case 'normal':
default:
$result = $a*$b;
break;
}
return $result;
}

protected function getConfig($key)
{
$aConfig['multitype'] = 'strong';
$aConfig['multimodificator'] = 2;
return $aConfig[$key];
}
}

Тестируем метод multi() с помощью одного мока для getConfig(), который возвращает разные значения, в зависимости от аргумента 'multitype' или 'multimodificator'.

class MyClassTest extends PHPUnit_Framework_TestCase
{
function testmulti()
{
$mockMy = $this->getMock('\MyClass', array('getConfig'));
$mockMy->expects($this->any())
->method('getConfig')
->with(
$this->logicalOr(
$this->equalTo('multitype'),
$this->equalTo('multimodificator')
)
)
->will(
$this->returnCallback(
function($arg)
{
$retValue = null;
switch($arg)
{
case "multitype";
$retValue = "strong";
break;

case "multimodificator";
$retValue = 2;
break;
}
return $retValue;
}
)
);
$this->assertEquals(8, $mockMy->multi(2,2));
}
}

программирование, phpunit, тестирование, php

Previous post Next post
Up