forked from UnionOfRAD/lithium
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MockerChain to make assertions easier and extendible.
- Loading branch information
Blaine Schmeisser
committed
Jan 17, 2013
1 parent
77a0f46
commit 8c138f6
Showing
5 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
<?php | ||
/** | ||
* Lithium: the most rad php framework | ||
* | ||
* @copyright Copyright 2013, Union of RAD (http://union-of-rad.org) | ||
* @license http://opensource.org/licenses/bsd-license.php The BSD License | ||
*/ | ||
|
||
namespace lithium\test; | ||
|
||
/** | ||
* Mocker chain is used to aid in assertion of method calls. | ||
* | ||
* Asserting if `method1` was not called | ||
* {{{ | ||
* $mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
* $this->assertFalse(Mocker::chain($mock)->called('method1')->success()); | ||
* }}} | ||
* | ||
* Asserting if `method1` was called 2 times | ||
* {{{ | ||
* $mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
* $this->assertTrue(Mocker::chain($mock)->called('method1')->eq(2)->success()); | ||
* }}} | ||
* | ||
* Asserting if `method2` was called after `method1` | ||
* {{{ | ||
* $mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
* $this->assertTrue(Mocker::chain($mock)->called('method1')->called('method2')->success()); | ||
* }}} | ||
* | ||
* Asserting if `method2` was called after `method1`, and `method2` had specific arguments. | ||
* {{{ | ||
* $mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
* $this->assertTrue(Mocker::chain($mock) | ||
* ->called('method1') | ||
* ->called('method2')->with('foo', 'bar') | ||
* ->success()); | ||
* }}} | ||
*/ | ||
class MockerChain extends \lithium\core\Object { | ||
|
||
/** | ||
* Data to be used in the class. | ||
* | ||
* `results` Cached mock results | ||
* `method` Method we are asserting | ||
* `args` Args we are asserting | ||
* `success` Success flag | ||
* `callTime` Last method call | ||
* | ||
* @var array | ||
*/ | ||
protected $_data = array( | ||
'results' => null, | ||
'method' => false, | ||
'args' => false, | ||
'success' => true, | ||
'callTime' => 0, | ||
); | ||
|
||
/** | ||
* Saves the results from the mock. | ||
* | ||
* @param array $results Results from the mock | ||
*/ | ||
public function __construct($results) { | ||
$this->_data['results'] = $results; | ||
} | ||
|
||
/** | ||
* Validates that a given methodis called a set number of times. | ||
* | ||
* @param string $comparison Comparison type 'gt', 'gte', 'lt', 'lte', or 'eq'. | ||
* @param array $args The first argument is the expected result. | ||
* @return object | ||
*/ | ||
public function __call($comparison, $args) { | ||
$methodExists = in_array($comparison, array('gt', 'gte', 'lt', 'lte', 'eq'), true); | ||
if (!$this->_data['success'] || !$methodExists) { | ||
return $this; | ||
} | ||
if (count($args) === 0 || !is_int($args[0])) { | ||
$this->_data['success'] = false; | ||
return $this; | ||
} | ||
$result = 0; | ||
$expected = $args[0]; | ||
$method = $this->_data['method']; | ||
$args = $this->_data['args']; | ||
foreach ($this->_data['results'][$method] as $call) { | ||
$correctTime = $this->_data['callTime'] <= $call['time']; | ||
$correctArgs = !is_array($args) || $args === $call['args']; | ||
if ($correctTime && $correctArgs) { | ||
$this->_data['callTime'] = $call['time']; | ||
$result++; | ||
} | ||
} | ||
switch ($comparison) { | ||
case 'gt': | ||
$this->_data['success'] = $result > $expected; | ||
break; | ||
case 'gte': | ||
$this->_data['success'] = $result >= $expected; | ||
break; | ||
case 'lt': | ||
$this->_data['success'] = $result < $expected; | ||
break; | ||
case 'lte': | ||
$this->_data['success'] = $result <= $expected; | ||
break; | ||
case 'eq': | ||
$this->_data['success'] = $result === $expected; | ||
break; | ||
} | ||
return $this; | ||
} | ||
|
||
/** | ||
* Valides the method was called after the last call. | ||
* | ||
* @param string $method Method to assert | ||
* @return object | ||
*/ | ||
function called($method) { | ||
if (!$this->_data['success']) { | ||
return $this; | ||
} | ||
|
||
$this->_data['method'] = $method; | ||
$this->_data['args'] = false; | ||
if (!isset($this->_data['results'][$method])) { | ||
$this->_data['success'] = false; | ||
return $this; | ||
} | ||
|
||
foreach ($this->_data['results'][$method] as $call) { | ||
if ($this->_data['callTime'] < $call['time']) { | ||
$this->_data['callTime'] = $call['time']; | ||
return $this; | ||
} | ||
} | ||
|
||
$this->_data['success'] = false; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Will further narrow down the original 'called' method. | ||
* | ||
* Valides the cached method name was called with these args | ||
* | ||
* @param mixed $arg,... Optional arguments to test against | ||
* @return object | ||
*/ | ||
public function with() { | ||
if (!$this->_data['success']) { | ||
return $this; | ||
} | ||
|
||
$method = $this->_data['method']; | ||
$this->_data['args'] = $args = func_get_args(); | ||
|
||
foreach ($this->_data['results'][$method] as $call) { | ||
$correctTime = $this->_data['callTime'] <= $call['time']; | ||
$correctArgs = $args === $call['args']; | ||
if ($correctTime && $correctArgs) { | ||
$this->_data['callTime'] = $call['time']; | ||
return $this; | ||
} | ||
} | ||
|
||
$this->_data['success'] = false; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Gives back the success flag | ||
* | ||
* @return bool | ||
*/ | ||
public function success() { | ||
$success = $this->_data['success']; | ||
$this->_data = array( | ||
'results' => $this->_data['results'], | ||
'method' => false, | ||
'args' => false, | ||
'success' => true, | ||
'callTime' => 0, | ||
); | ||
return $success; | ||
} | ||
|
||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<?php | ||
/** | ||
* Lithium: the most rad php framework | ||
* | ||
* @copyright Copyright 2013, Union of RAD (http://union-of-rad.org) | ||
* @license http://opensource.org/licenses/bsd-license.php The BSD License | ||
*/ | ||
|
||
namespace lithium\tests\cases\test; | ||
|
||
use lithium\test\Mocker; | ||
|
||
class MockerChainTest extends \lithium\test\Unit { | ||
|
||
public function setUp() { | ||
Mocker::register(); | ||
} | ||
|
||
public function testStartSuccessful() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->success()); | ||
} | ||
|
||
public function testBasicNotCalled() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertFalse($chain->called('method1')->success()); | ||
} | ||
|
||
public function testBasicCalled() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->called('method1')->success()); | ||
} | ||
|
||
public function testCalledWith() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1('foo'); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->called('method1')->success()); | ||
$this->assertFalse($chain->called('method1')->with('bar')->success()); | ||
$this->assertTrue($chain->called('method1')->with('foo')->success()); | ||
$this->assertFalse($chain->called('method1')->with('foo', 'bar')->success()); | ||
} | ||
|
||
public function testMethodCalledBefore() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1(); | ||
$mock->method2(); | ||
$mock->method1(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->called('method1') | ||
->called('method2') | ||
->called('method1') | ||
->success()); | ||
$this->assertFalse($chain->called('method2') | ||
->called('method1') | ||
->called('method1') | ||
->success()); | ||
} | ||
|
||
public function testMethodWithParamsCalledBefore() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1('foo'); | ||
$mock->method2('bar'); | ||
$mock->method1('baz'); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->called('method1') | ||
->called('method2')->with('bar') | ||
->called('method1') | ||
->success()); | ||
$this->assertFalse($chain->called('method1')->with('bar') | ||
->called('method2')->with('bar') | ||
->called('method1') | ||
->success()); | ||
$this->assertFalse($chain->called('method1') | ||
->called('method2')->with('bar') | ||
->called('method1')->with('bar') | ||
->success()); | ||
} | ||
|
||
public function testMethodCalledSpecificTimes() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1(); | ||
$mock->method2(); | ||
$mock->method1(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertFalse($chain->called('method2')->eq(2)->success()); | ||
$this->assertTrue($chain->called('method1')->eq(2)->success()); | ||
$this->assertTrue($chain->called('method1')->gt(0)->success()); | ||
$this->assertTrue($chain->called('method1')->gte(1)->success()); | ||
$this->assertTrue($chain->called('method1')->lt(3)->success()); | ||
$this->assertTrue($chain->called('method1')->lte(2)->success()); | ||
$this->assertFalse($chain->called('method1')->lte(1)->success()); | ||
} | ||
|
||
public function testMultipleCallsWithArgsAndSpecificCalled() { | ||
$mock = new \lithium\tests\mocks\test\mockStdClass\Mock(); | ||
$mock->method1('foo', 'bar'); | ||
$mock->method1('foo', 'bar'); | ||
$mock->method1('foo', 'bar'); | ||
$mock->method2('baz'); | ||
$mock->method2('baz'); | ||
$mock->method1(); | ||
$chain = Mocker::chain($mock); | ||
|
||
$this->assertTrue($chain->called('method1')->with('foo', 'bar')->eq(3)->success()); | ||
$this->assertTrue($chain->called('method2')->with('baz')->eq(2)->success()); | ||
$this->assertTrue($chain->called('method1')->with()->eq(1)->success()); | ||
|
||
$this->assertTrue($chain->called('method1')->with('foo', 'bar')->eq(3) | ||
->called('method2')->with('baz')->eq(2) | ||
->called('method1')->with()->eq(1)->success()); | ||
} | ||
|
||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters