/
PHPMock.php
138 lines (124 loc) · 4.43 KB
/
PHPMock.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
namespace phpmock\phpunit;
use phpmock\integration\MockDelegateFunctionBuilder;
use phpmock\MockBuilder;
use phpmock\Deactivatable;
/**
* Adds building a function mock functionality into \PHPUnit\Framework\TestCase.
*
* Use this trait in your \PHPUnit\Framework\TestCase:
* <code>
* <?php
*
* namespace foo;
*
* class FooTest extends \PHPUnit\Framework\TestCase
* {
*
* use \phpmock\phpunit\PHPMock;
*
* public function testBar()
* {
* $time = $this->getFunctionMock(__NAMESPACE__, "time");
* $time->expects($this->once())->willReturn(3);
* $this->assertEquals(3, time());
* }
* }
* </code>
*
* @author Markus Malkusch <markus@malkusch.de>
* @link bitcoin:1335STSwu9hST4vcMRppEPgENMHD2r1REK Donations
* @license http://www.wtfpl.net/txt/copying/ WTFPL
*/
trait PHPMock
{
/**
* Returns a builder object to create mock objects using a fluent interface.
*
* This method exists in \PHPUnit\Framework\TestCase.
*
* @param string $className Name of the class to mock.
* @return \PHPUnit_Framework_MockObject_MockBuilder
* @see \PHPUnit\Framework\TestCase::getMockBuilder()
* @internal
*/
abstract protected function getMockBuilder($className);
/**
* Returns the test result.
*
* This method exists in \PHPUnit\Framework\TestCase.
*
* @return \PHPUnit\Framework\TestResult The test result.
* @see \PHPUnit\Framework\TestCase::getTestResultObject()
* @internal
*/
abstract protected function getTestResultObject();
/**
* Returns the enabled function mock.
*
* This mock will be disabled automatically after the test run.
*
* @param string $namespace The function namespace.
* @param string $name The function name.
*
* @return \PHPUnit_Framework_MockObject_MockObject The PHPUnit mock.
*/
public function getFunctionMock($namespace, $name)
{
$delegateBuilder = new MockDelegateFunctionBuilder();
$delegateBuilder->build($name);
$mock = $this->getMockBuilder($delegateBuilder->getFullyQualifiedClassName())->getMockForAbstractClass();
$mock->__phpunit_getInvocationMocker()->addMatcher(new DefaultArgumentRemover());
$functionMockBuilder = new MockBuilder();
$functionMockBuilder->setNamespace($namespace)
->setName($name)
->setFunctionProvider($mock);
$functionMock = $functionMockBuilder->build();
$functionMock->enable();
$this->registerForTearDown($functionMock);
$proxy = new MockObjectProxy($mock);
return $proxy;
}
/**
* Automatically disable function mocks after the test was run.
*
* If you use getFunctionMock() you don't need this method. This method
* is meant for a Deactivatable (e.g. a MockEnvironment) which was
* directly created with PHPMock's API.
*
* @param Deactivatable $deactivatable The function mocks.
*/
public function registerForTearDown(Deactivatable $deactivatable)
{
$result = $this->getTestResultObject();
$result->addListener(new MockDisabler($deactivatable));
}
/**
* Defines the mocked function in the given namespace.
*
* In most cases you don't have to call this method. {@link getFunctionMock()}
* is doing this for you. But if the mock is defined after the first call in the
* tested class, the tested class doesn't resolve to the mock. This is
* documented in Bug #68541. You therefore have to define the namespaced
* function before the first call (e.g. with the beforeClass annotation).
*
* Defining the function has no side effects. If the function was
* already defined this method does nothing.
*
* @see getFunctionMock()
* @link https://bugs.php.net/bug.php?id=68541 Bug #68541
*
* @param string $namespace The function namespace.
* @param string $name The function name.
*/
public static function defineFunctionMock($namespace, $name)
{
$functionMockBuilder = new MockBuilder();
$functionMockBuilder->setNamespace($namespace)
->setName($name)
->setFunction(function () {
})
->build()
->define();
}
}