3
3
4
4
use Codeception \Specify \Config ;
5
5
use Codeception \Specify \ConfigBuilder ;
6
+ use Codeception \Specify \ObjectProperty ;
6
7
7
- trait Specify {
8
+ trait Specify
9
+ {
8
10
9
11
private $ beforeSpecify = array ();
10
12
private $ afterSpecify = array ();
@@ -27,7 +29,7 @@ private function specifyInit()
27
29
if (!$ this ->specifyConfig ) $ this ->specifyConfig = Config::create ();
28
30
}
29
31
30
- function specify ($ specification , \Closure $ callable = null , $ params = [])
32
+ function specify ($ specification , \Closure $ callable = null , $ params = [])
31
33
{
32
34
if (!$ callable ) return ;
33
35
$ this ->specifyInit ();
@@ -38,7 +40,7 @@ function specify($specification, \Closure $callable = null, $params = [])
38
40
39
41
$ this ->setName ($ newName );
40
42
41
- $ properties = get_object_vars ( $ this );
43
+ $ properties = $ this -> getSpecifyObjectProperties ( );
42
44
43
45
// prepare for execution
44
46
$ throws = $ this ->getSpecifyExpectedException ($ params );
@@ -58,13 +60,12 @@ function specify($specification, \Closure $callable = null, $params = [])
58
60
if ($ closure instanceof \Closure) $ closure ->__invoke ();
59
61
}
60
62
}
63
+
61
64
$ this ->specifyExecute ($ test , $ throws , $ example );
62
65
63
66
// restore object properties
64
- foreach ($ properties as $ property => $ val ) {
65
- if ($ this ->specifyConfig ->propertyIgnored ($ property )) continue ;
66
- $ this ->$ property = $ val ;
67
- }
67
+ $ this ->specifyRestoreProperties ($ properties );
68
+
68
69
if (!empty ($ this ->afterSpecify ) && is_array ($ this ->afterSpecify )) {
69
70
foreach ($ this ->afterSpecify as $ closure ) {
70
71
if ($ closure instanceof \Closure) $ closure ->__invoke ();
@@ -120,8 +121,10 @@ private function specifyExecute($test, $throws = false, $examples = array())
120
121
}
121
122
122
123
$ result = $ this ->getTestResultObject ();
124
+
123
125
try {
124
126
call_user_func_array ($ test , $ examples );
127
+ $ this ->specifyCheckMockObjects ();
125
128
} catch (\PHPUnit_Framework_AssertionFailedError $ e ) {
126
129
if ($ throws !== get_class ($ e )){
127
130
$ result ->addFailure (clone ($ this ), $ e , $ result ->time ());
@@ -179,29 +182,107 @@ function cleanSpecify()
179
182
}
180
183
181
184
/**
182
- * @param $properties
183
- * @return array
185
+ * @param ObjectProperty[] $properties
184
186
*/
185
187
private function specifyCloneProperties ($ properties )
186
188
{
187
- foreach ($ properties as $ property => $ val ) {
188
- if ( $ this -> specifyConfig -> propertyIgnored ( $ property )) {
189
- continue ;
190
- }
191
- if ($ this ->specifyConfig ->classIgnored ($ val )) {
189
+ foreach ($ properties as $ property ) {
190
+ $ propertyName = $ property -> getName ();
191
+ $ propertyValue = $ property -> getValue () ;
192
+
193
+ if ($ this ->specifyConfig ->classIgnored ($ propertyValue )) {
192
194
continue ;
193
195
}
194
196
195
- if ($ this ->specifyConfig ->propertyIsShallowCloned ($ property )) {
196
- if (is_object ($ val )) {
197
- $ this -> $ property = clone $ val ;
197
+ if ($ this ->specifyConfig ->propertyIsShallowCloned ($ propertyName )) {
198
+ if (is_object ($ propertyValue )) {
199
+ $ property -> setValue ( clone $ propertyValue ) ;
198
200
} else {
199
- $ this -> $ property = $ val ;
201
+ $ property -> setValue ( $ propertyValue ) ;
200
202
}
201
203
}
202
- if ($ this ->specifyConfig ->propertyIsDeeplyCloned ($ property )) {
203
- $ this ->$ property = $ this ->copier ->copy ($ val );
204
+
205
+ if ($ this ->specifyConfig ->propertyIsDeeplyCloned ($ propertyName )) {
206
+ $ property ->setValue ($ this ->copier ->copy ($ propertyValue ));
204
207
}
205
208
}
206
209
}
210
+
211
+ /**
212
+ * @param ObjectProperty[] $properties
213
+ */
214
+ private function specifyRestoreProperties ($ properties )
215
+ {
216
+ foreach ($ properties as $ property ) {
217
+ $ property ->restoreValue ();
218
+ }
219
+ }
220
+
221
+ /**
222
+ * @return ObjectProperty[]
223
+ */
224
+ private function getSpecifyObjectProperties ()
225
+ {
226
+ $ objectReflection = new \ReflectionObject ($ this );
227
+ $ propertiesToClone = $ objectReflection ->getProperties ();
228
+
229
+ if (($ classProperties = $ this ->specifyGetClassPrivateProperties ()) !== []) {
230
+ $ propertiesToClone = array_merge ($ propertiesToClone , $ classProperties );
231
+ }
232
+
233
+ $ properties = [];
234
+
235
+ foreach ($ propertiesToClone as $ property ) {
236
+ if ($ this ->specifyConfig ->propertyIgnored ($ property ->getName ())) {
237
+ continue ;
238
+ }
239
+
240
+ $ properties [] = new ObjectProperty ($ this , $ property );
241
+ }
242
+
243
+ // isolate mockObjects property from PHPUnit_Framework_TestCase
244
+ if (($ phpUnitReflection = $ this ->specifyGetPhpUnitReflection ()) !== null ) {
245
+ $ properties [] = $ mockObjects = new ObjectProperty (
246
+ $ this , $ phpUnitReflection ->getProperty ('mockObjects ' )
247
+ );
248
+
249
+ // remove all mock objects inherited from parent scope(s)
250
+ $ mockObjects ->setValue ([]);
251
+ }
252
+
253
+ return $ properties ;
254
+ }
255
+
256
+ private function specifyCheckMockObjects ()
257
+ {
258
+ if (($ phpUnitReflection = $ this ->specifyGetPhpUnitReflection ()) !== null ) {
259
+ $ verifyMockObjects = $ phpUnitReflection ->getMethod ('verifyMockObjects ' );
260
+ $ verifyMockObjects ->setAccessible (true );
261
+ $ verifyMockObjects ->invoke ($ this );
262
+ }
263
+ }
264
+
265
+ private function specifyGetClassPrivateProperties ()
266
+ {
267
+ static $ properties = [];
268
+
269
+ if (!isset ($ properties [__CLASS__ ])) {
270
+ $ reflection = new \ReflectionClass (__CLASS__ );
271
+
272
+ $ properties [__CLASS__ ] = (get_class ($ this ) !== __CLASS__ )
273
+ ? $ reflection ->getProperties (\ReflectionProperty::IS_PRIVATE ) : [];
274
+ }
275
+
276
+ return $ properties [__CLASS__ ];
277
+ }
278
+
279
+ /**
280
+ * @return \ReflectionClass|null
281
+ */
282
+ private function specifyGetPhpUnitReflection ()
283
+ {
284
+ if ($ this instanceof \PHPUnit_Framework_TestCase) {
285
+ return new \ReflectionClass ('\PHPUnit_Framework_TestCase ' );
286
+ }
287
+ }
207
288
}
0 commit comments