33
44use Codeception \Specify \Config ;
55use Codeception \Specify \ConfigBuilder ;
6+ use Codeception \Specify \ObjectProperty ;
67
7- trait Specify {
8+ trait Specify
9+ {
810
911 private $ beforeSpecify = array ();
1012 private $ afterSpecify = array ();
@@ -27,7 +29,7 @@ private function specifyInit()
2729 if (!$ this ->specifyConfig ) $ this ->specifyConfig = Config::create ();
2830 }
2931
30- function specify ($ specification , \Closure $ callable = null , $ params = [])
32+ function specify ($ specification , \Closure $ callable = null , $ params = [])
3133 {
3234 if (!$ callable ) return ;
3335 $ this ->specifyInit ();
@@ -38,7 +40,7 @@ function specify($specification, \Closure $callable = null, $params = [])
3840
3941 $ this ->setName ($ newName );
4042
41- $ properties = get_object_vars ( $ this );
43+ $ properties = $ this -> getSpecifyObjectProperties ( );
4244
4345 // prepare for execution
4446 $ throws = $ this ->getSpecifyExpectedException ($ params );
@@ -58,13 +60,12 @@ function specify($specification, \Closure $callable = null, $params = [])
5860 if ($ closure instanceof \Closure) $ closure ->__invoke ();
5961 }
6062 }
63+
6164 $ this ->specifyExecute ($ test , $ throws , $ example );
6265
6366 // 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+
6869 if (!empty ($ this ->afterSpecify ) && is_array ($ this ->afterSpecify )) {
6970 foreach ($ this ->afterSpecify as $ closure ) {
7071 if ($ closure instanceof \Closure) $ closure ->__invoke ();
@@ -120,8 +121,10 @@ private function specifyExecute($test, $throws = false, $examples = array())
120121 }
121122
122123 $ result = $ this ->getTestResultObject ();
124+
123125 try {
124126 call_user_func_array ($ test , $ examples );
127+ $ this ->specifyCheckMockObjects ();
125128 } catch (\PHPUnit_Framework_AssertionFailedError $ e ) {
126129 if ($ throws !== get_class ($ e )){
127130 $ result ->addFailure (clone ($ this ), $ e , $ result ->time ());
@@ -179,29 +182,86 @@ function cleanSpecify()
179182 }
180183
181184 /**
182- * @param $properties
183- * @return array
185+ * @param ObjectProperty[] $properties
184186 */
185187 private function specifyCloneProperties ($ properties )
186188 {
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 )) {
192194 continue ;
193195 }
194196
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 ) ;
198200 } else {
199- $ this -> $ property = $ val ;
201+ $ property -> setValue ( $ propertyValue ) ;
200202 }
201203 }
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 ));
204207 }
205208 }
206209 }
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+ $ properties = [];
227+
228+ foreach (get_object_vars ($ this ) as $ property => $ value ) {
229+ if ($ this ->specifyConfig ->propertyIgnored ($ property )) {
230+ continue ;
231+ }
232+
233+ $ properties [] = new ObjectProperty ($ this , $ property , $ value );
234+ }
235+
236+ // isolate mockObjects property from PHPUnit_Framework_TestCase
237+ if (($ phpUnitReflection = $ this ->specifyGetPhpUnitReflection ()) !== null ) {
238+ $ properties [] = $ mockObjects = new ObjectProperty (
239+ $ this , $ phpUnitReflection ->getProperty ('mockObjects ' )
240+ );
241+
242+ // remove all mock objects inherited from parent scope(s)
243+ $ mockObjects ->setValue ([]);
244+ }
245+
246+ return $ properties ;
247+ }
248+
249+ private function specifyCheckMockObjects ()
250+ {
251+ if (($ phpUnitReflection = $ this ->specifyGetPhpUnitReflection ()) !== null ) {
252+ $ verifyMockObjects = $ phpUnitReflection ->getMethod ('verifyMockObjects ' );
253+ $ verifyMockObjects ->setAccessible (true );
254+ $ verifyMockObjects ->invoke ($ this );
255+ }
256+ }
257+
258+ /**
259+ * @return \ReflectionClass|null
260+ */
261+ private function specifyGetPhpUnitReflection ()
262+ {
263+ if ($ this instanceof \PHPUnit_Framework_TestCase) {
264+ return new \ReflectionClass ('\PHPUnit_Framework_TestCase ' );
265+ }
266+ }
207267}
0 commit comments