PageRenderTime 196ms CodeModel.GetById 53ms app.highlight 88ms RepoModel.GetById 30ms app.codeStats 1ms

/app/vendors/simpletest/test/mock_objects_test.php

https://github.com/MrRio/wildflower
PHP | 994 lines | 860 code | 129 blank | 5 comment | 3 complexity | 9b0ee3e253d401e330ae90cf3e2f66eb MD5 | raw file
  1<?php
  2// $Id: mock_objects_test.php 1700 2008-03-24 16:17:48Z lastcraft $
  3require_once(dirname(__FILE__) . '/../autorun.php');
  4require_once(dirname(__FILE__) . '/../expectation.php');
  5require_once(dirname(__FILE__) . '/../mock_objects.php');
  6
  7class TestOfAnythingExpectation extends UnitTestCase {
  8
  9    function testSimpleInteger() {
 10        $expectation = new AnythingExpectation();
 11        $this->assertTrue($expectation->test(33));
 12        $this->assertTrue($expectation->test(false));
 13        $this->assertTrue($expectation->test(null));
 14    }
 15}
 16
 17class TestOfParametersExpectation extends UnitTestCase {
 18
 19    function testEmptyMatch() {
 20        $expectation = new ParametersExpectation(array());
 21        $this->assertTrue($expectation->test(array()));
 22        $this->assertFalse($expectation->test(array(33)));
 23    }
 24
 25    function testSingleMatch() {
 26        $expectation = new ParametersExpectation(array(0));
 27        $this->assertFalse($expectation->test(array(1)));
 28        $this->assertTrue($expectation->test(array(0)));
 29    }
 30
 31    function testAnyMatch() {
 32        $expectation = new ParametersExpectation(false);
 33        $this->assertTrue($expectation->test(array()));
 34        $this->assertTrue($expectation->test(array(1, 2)));
 35    }
 36
 37    function testMissingParameter() {
 38        $expectation = new ParametersExpectation(array(0));
 39        $this->assertFalse($expectation->test(array()));
 40    }
 41
 42    function testNullParameter() {
 43        $expectation = new ParametersExpectation(array(null));
 44        $this->assertTrue($expectation->test(array(null)));
 45        $this->assertFalse($expectation->test(array()));
 46    }
 47
 48    function testAnythingExpectations() {
 49        $expectation = new ParametersExpectation(array(new AnythingExpectation()));
 50        $this->assertFalse($expectation->test(array()));
 51        $this->assertIdentical($expectation->test(array(null)), true);
 52        $this->assertIdentical($expectation->test(array(13)), true);
 53    }
 54
 55    function testOtherExpectations() {
 56        $expectation = new ParametersExpectation(
 57                array(new PatternExpectation('/hello/i')));
 58        $this->assertFalse($expectation->test(array('Goodbye')));
 59        $this->assertTrue($expectation->test(array('hello')));
 60        $this->assertTrue($expectation->test(array('Hello')));
 61    }
 62
 63    function testIdentityOnly() {
 64        $expectation = new ParametersExpectation(array("0"));
 65        $this->assertFalse($expectation->test(array(0)));
 66        $this->assertTrue($expectation->test(array("0")));
 67    }
 68
 69    function testLongList() {
 70        $expectation = new ParametersExpectation(
 71                array("0", 0, new AnythingExpectation(), false));
 72        $this->assertTrue($expectation->test(array("0", 0, 37, false)));
 73        $this->assertFalse($expectation->test(array("0", 0, 37, true)));
 74        $this->assertFalse($expectation->test(array("0", 0, 37)));
 75    }
 76}
 77
 78class TestOfSimpleSignatureMap extends UnitTestCase {
 79
 80    function testEmpty() {
 81        $map = new SimpleSignatureMap();
 82        $this->assertFalse($map->isMatch("any", array()));
 83        $this->assertNull($map->findFirstAction("any", array()));
 84    }
 85
 86    function testExactReference() {
 87        $map = new SimpleSignatureMap();
 88        $ref = "Fred";
 89        $map->add(array(0), $ref);
 90        $this->assertEqual($map->findFirstAction(array(0)), "Fred");
 91        $ref2 = &$map->findFirstAction(array(0));
 92        $this->assertReference($ref2, $ref);
 93    }
 94    
 95    function testDifferentCallSignaturesCanHaveDifferentReferences() {
 96        $map = new SimpleSignatureMap();
 97        $fred = 'Fred';
 98        $jim = 'jim';
 99        $map->add(array(0), $fred);
100        $map->add(array('0'), $jim);
101        $this->assertReference($fred, $map->findFirstAction(array(0)));
102        $this->assertReference($jim, $map->findFirstAction(array('0')));
103    }
104
105    function testWildcard() {
106        $fred = 'Fred';
107        $map = new SimpleSignatureMap();
108        $map->add(array(new AnythingExpectation(), 1, 3), $fred);
109        $this->assertTrue($map->isMatch(array(2, 1, 3)));
110        $this->assertReference($map->findFirstAction(array(2, 1, 3)), $fred);
111    }
112
113    function testAllWildcard() {
114        $fred = 'Fred';
115        $map = new SimpleSignatureMap();
116        $this->assertFalse($map->isMatch(array(2, 1, 3)));
117        $map->add('', $fred);
118        $this->assertTrue($map->isMatch(array(2, 1, 3)));
119        $this->assertReference($map->findFirstAction(array(2, 1, 3)), $fred);
120    }
121
122    function testOrdering() {
123        $map = new SimpleSignatureMap();
124        $map->add(array(1, 2), new SimpleByValue("1, 2"));
125        $map->add(array(1, 3), new SimpleByValue("1, 3"));
126        $map->add(array(1), new SimpleByValue("1"));
127        $map->add(array(1, 4), new SimpleByValue("1, 4"));
128        $map->add(array(new AnythingExpectation()), new SimpleByValue("Any"));
129        $map->add(array(2), new SimpleByValue("2"));
130        $map->add("", new SimpleByValue("Default"));
131        $map->add(array(), new SimpleByValue("None"));
132        $this->assertEqual($map->findFirstAction(array(1, 2)), new SimpleByValue("1, 2"));
133        $this->assertEqual($map->findFirstAction(array(1, 3)), new SimpleByValue("1, 3"));
134        $this->assertEqual($map->findFirstAction(array(1, 4)), new SimpleByValue("1, 4"));
135        $this->assertEqual($map->findFirstAction(array(1)), new SimpleByValue("1"));
136        $this->assertEqual($map->findFirstAction(array(2)), new SimpleByValue("Any"));
137        $this->assertEqual($map->findFirstAction(array(3)), new SimpleByValue("Any"));
138        $this->assertEqual($map->findFirstAction(array()), new SimpleByValue("Default"));
139    }
140}
141
142class TestOfCallSchedule extends UnitTestCase {
143    function testCanBeSetToAlwaysReturnTheSameReference() {
144        $a = 5;
145        $schedule = &new SimpleCallSchedule();
146        $schedule->register('aMethod', false, new SimpleByReference($a));
147        $this->assertReference($schedule->respond(0, 'aMethod', array()), $a);
148        $this->assertReference($schedule->respond(1, 'aMethod', array()), $a);
149    }
150
151    function testSpecificSignaturesOverrideTheAlwaysCase() {
152        $any = 'any';
153        $one = 'two';
154        $schedule = &new SimpleCallSchedule();
155        $schedule->register('aMethod', array(1), new SimpleByReference($one));
156        $schedule->register('aMethod', false, new SimpleByReference($any));
157        $this->assertReference($schedule->respond(0, 'aMethod', array(2)), $any);
158        $this->assertReference($schedule->respond(0, 'aMethod', array(1)), $one);
159    }
160    
161    function testReturnsCanBeSetOverTime() {
162        $one = 'one';
163        $two = 'two';
164        $schedule = &new SimpleCallSchedule();
165        $schedule->registerAt(0, 'aMethod', false, new SimpleByReference($one));
166        $schedule->registerAt(1, 'aMethod', false, new SimpleByReference($two));
167        $this->assertReference($schedule->respond(0, 'aMethod', array()), $one);
168        $this->assertReference($schedule->respond(1, 'aMethod', array()), $two);
169    }
170    
171    function testReturnsOverTimecanBeAlteredByTheArguments() {
172        $one = '1';
173        $two = '2';
174        $two_a = '2a';
175        $schedule = &new SimpleCallSchedule();
176        $schedule->registerAt(0, 'aMethod', false, new SimpleByReference($one));
177        $schedule->registerAt(1, 'aMethod', array('a'), new SimpleByReference($two_a));
178        $schedule->registerAt(1, 'aMethod', false, new SimpleByReference($two));
179        $this->assertReference($schedule->respond(0, 'aMethod', array()), $one);
180        $this->assertReference($schedule->respond(1, 'aMethod', array()), $two);
181        $this->assertReference($schedule->respond(1, 'aMethod', array('a')), $two_a);
182    }
183    
184    function testCanReturnByValue() {
185        $a = 5;
186        $schedule = &new SimpleCallSchedule();
187        $schedule->register('aMethod', false, new SimpleByValue($a));
188        $this->assertClone($schedule->respond(0, 'aMethod', array()), $a);
189    }
190    
191    function testCanThrowException() {
192        if (version_compare(phpversion(), '5', '>=')) {
193            $schedule = &new SimpleCallSchedule();
194            $schedule->register('aMethod', false, new SimpleThrower(new Exception('Ouch')));
195            $this->expectException(new Exception('Ouch'));
196            $schedule->respond(0, 'aMethod', array());
197        }
198    }
199    
200    function testCanEmitError() {
201        $schedule = &new SimpleCallSchedule();
202        $schedule->register('aMethod', false, new SimpleErrorThrower('Ouch', E_USER_WARNING));
203        $this->expectError('Ouch');
204        $schedule->respond(0, 'aMethod', array());
205    }
206}
207
208class Dummy {
209    function Dummy() {
210    }
211
212    function aMethod() {
213        return true;
214    }
215
216    function anotherMethod() {
217        return true;
218    }
219}
220Mock::generate('Dummy');
221Mock::generate('Dummy', 'AnotherMockDummy');
222Mock::generate('Dummy', 'MockDummyWithExtraMethods', array('extraMethod'));
223
224class TestOfMockGeneration extends UnitTestCase {
225
226    function testCloning() {
227        $mock = &new MockDummy();
228        $this->assertTrue(method_exists($mock, "aMethod"));
229        $this->assertNull($mock->aMethod());
230    }
231
232    function testCloningWithExtraMethod() {
233        $mock = &new MockDummyWithExtraMethods();
234        $this->assertTrue(method_exists($mock, "extraMethod"));
235    }
236
237    function testCloningWithChosenClassName() {
238        $mock = &new AnotherMockDummy();
239        $this->assertTrue(method_exists($mock, "aMethod"));
240    }
241}
242
243class TestOfMockReturns extends UnitTestCase {
244
245    function testDefaultReturn() {
246        $mock = &new MockDummy();
247        $mock->setReturnValue("aMethod", "aaa");
248        $this->assertIdentical($mock->aMethod(), "aaa");
249        $this->assertIdentical($mock->aMethod(), "aaa");
250    }
251
252    function testParameteredReturn() {
253        $mock = &new MockDummy();
254        $mock->setReturnValue('aMethod', 'aaa', array(1, 2, 3));
255        $this->assertNull($mock->aMethod());
256        $this->assertIdentical($mock->aMethod(1, 2, 3), 'aaa');
257    }
258
259    function testReferenceReturned() {
260        $mock = &new MockDummy();
261        $object = new Dummy();
262        $mock->setReturnReference('aMethod', $object, array(1, 2, 3));
263        $this->assertReference($zref = &$mock->aMethod(1, 2, 3), $object);
264    }
265
266    function testPatternMatchReturn() {
267        $mock = &new MockDummy();
268        $mock->setReturnValue(
269                "aMethod",
270                "aaa",
271                array(new PatternExpectation('/hello/i')));
272        $this->assertIdentical($mock->aMethod('Hello'), "aaa");
273        $this->assertNull($mock->aMethod('Goodbye'));
274    }
275
276    function testMultipleMethods() {
277        $mock = &new MockDummy();
278        $mock->setReturnValue("aMethod", 100, array(1));
279        $mock->setReturnValue("aMethod", 200, array(2));
280        $mock->setReturnValue("anotherMethod", 10, array(1));
281        $mock->setReturnValue("anotherMethod", 20, array(2));
282        $this->assertIdentical($mock->aMethod(1), 100);
283        $this->assertIdentical($mock->anotherMethod(1), 10);
284        $this->assertIdentical($mock->aMethod(2), 200);
285        $this->assertIdentical($mock->anotherMethod(2), 20);
286    }
287
288    function testReturnSequence() {
289        $mock = &new MockDummy();
290        $mock->setReturnValueAt(0, "aMethod", "aaa");
291        $mock->setReturnValueAt(1, "aMethod", "bbb");
292        $mock->setReturnValueAt(3, "aMethod", "ddd");
293        $this->assertIdentical($mock->aMethod(), "aaa");
294        $this->assertIdentical($mock->aMethod(), "bbb");
295        $this->assertNull($mock->aMethod());
296        $this->assertIdentical($mock->aMethod(), "ddd");
297    }
298
299    function testReturnReferenceSequence() {
300        $mock = &new MockDummy();
301        $object = new Dummy();
302        $mock->setReturnReferenceAt(1, "aMethod", $object);
303        $this->assertNull($mock->aMethod());
304        $this->assertReference($zref =& $mock->aMethod(), $object);
305        $this->assertNull($mock->aMethod());
306    }
307
308    function testComplicatedReturnSequence() {
309        $mock = &new MockDummy();
310        $object = new Dummy();
311        $mock->setReturnValueAt(1, "aMethod", "aaa", array("a"));
312        $mock->setReturnValueAt(1, "aMethod", "bbb");
313        $mock->setReturnReferenceAt(2, "aMethod", $object, array('*', 2));
314        $mock->setReturnValueAt(2, "aMethod", "value", array('*', 3));
315        $mock->setReturnValue("aMethod", 3, array(3));
316        $this->assertNull($mock->aMethod());
317        $this->assertEqual($mock->aMethod("a"), "aaa");
318        $this->assertReference($zref =& $mock->aMethod(1, 2), $object);
319        $this->assertEqual($mock->aMethod(3), 3);
320        $this->assertNull($mock->aMethod());
321    }
322
323    function testMultipleMethodSequences() {
324        $mock = &new MockDummy();
325        $mock->setReturnValueAt(0, "aMethod", "aaa");
326        $mock->setReturnValueAt(1, "aMethod", "bbb");
327        $mock->setReturnValueAt(0, "anotherMethod", "ccc");
328        $mock->setReturnValueAt(1, "anotherMethod", "ddd");
329        $this->assertIdentical($mock->aMethod(), "aaa");
330        $this->assertIdentical($mock->anotherMethod(), "ccc");
331        $this->assertIdentical($mock->aMethod(), "bbb");
332        $this->assertIdentical($mock->anotherMethod(), "ddd");
333    }
334
335    function testSequenceFallback() {
336        $mock = &new MockDummy();
337        $mock->setReturnValueAt(0, "aMethod", "aaa", array('a'));
338        $mock->setReturnValueAt(1, "aMethod", "bbb", array('a'));
339        $mock->setReturnValue("aMethod", "AAA");
340        $this->assertIdentical($mock->aMethod('a'), "aaa");
341        $this->assertIdentical($mock->aMethod('b'), "AAA");
342    }
343
344    function testMethodInterference() {
345        $mock = &new MockDummy();
346        $mock->setReturnValueAt(0, "anotherMethod", "aaa");
347        $mock->setReturnValue("aMethod", "AAA");
348        $this->assertIdentical($mock->aMethod(), "AAA");
349        $this->assertIdentical($mock->anotherMethod(), "aaa");
350    }
351}
352
353class TestOfMockExpectationsThatPass extends UnitTestCase {
354
355    function testAnyArgument() {
356        $mock = &new MockDummy();
357        $mock->expect('aMethod', array('*'));
358        $mock->aMethod(1);
359        $mock->aMethod('hello');
360    }
361
362    function testAnyTwoArguments() {
363        $mock = &new MockDummy();
364        $mock->expect('aMethod', array('*', '*'));
365        $mock->aMethod(1, 2);
366    }
367
368    function testSpecificArgument() {
369        $mock = &new MockDummy();
370        $mock->expect('aMethod', array(1));
371        $mock->aMethod(1);
372    }
373
374    function testExpectation() {
375        $mock = &new MockDummy();
376        $mock->expect('aMethod', array(new IsAExpectation('Dummy')));
377        $mock->aMethod(new Dummy());
378    }
379
380    function testArgumentsInSequence() {
381        $mock = &new MockDummy();
382        $mock->expectAt(0, 'aMethod', array(1, 2));
383        $mock->expectAt(1, 'aMethod', array(3, 4));
384        $mock->aMethod(1, 2);
385        $mock->aMethod(3, 4);
386    }
387
388    function testAtLeastOnceSatisfiedByOneCall() {
389        $mock = &new MockDummy();
390        $mock->expectAtLeastOnce('aMethod');
391        $mock->aMethod();
392    }
393
394    function testAtLeastOnceSatisfiedByTwoCalls() {
395        $mock = &new MockDummy();
396        $mock->expectAtLeastOnce('aMethod');
397        $mock->aMethod();
398        $mock->aMethod();
399    }
400
401    function testOnceSatisfiedByOneCall() {
402        $mock = &new MockDummy();
403        $mock->expectOnce('aMethod');
404        $mock->aMethod();
405    }
406
407    function testMinimumCallsSatisfiedByEnoughCalls() {
408        $mock = &new MockDummy();
409        $mock->expectMinimumCallCount('aMethod', 1);
410        $mock->aMethod();
411    }
412
413    function testMinimumCallsSatisfiedByTooManyCalls() {
414        $mock = &new MockDummy();
415        $mock->expectMinimumCallCount('aMethod', 3);
416        $mock->aMethod();
417        $mock->aMethod();
418        $mock->aMethod();
419        $mock->aMethod();
420    }
421
422    function testMaximumCallsSatisfiedByEnoughCalls() {
423        $mock = &new MockDummy();
424        $mock->expectMaximumCallCount('aMethod', 1);
425        $mock->aMethod();
426    }
427
428    function testMaximumCallsSatisfiedByNoCalls() {
429        $mock = &new MockDummy();
430        $mock->expectMaximumCallCount('aMethod', 1);
431    }
432}
433
434class MockWithInjectedTestCase extends SimpleMock {
435    function &_getCurrentTestCase() {
436        $context = &SimpleTest::getContext();
437        $test = &$context->getTest();
438        return $test->getMockedTest();
439    }
440}
441SimpleTest::setMockBaseClass('MockWithInjectedTestCase');
442Mock::generate('Dummy', 'MockDummyWithInjectedTestCase');
443SimpleTest::setMockBaseClass('SimpleMock');
444Mock::generate('SimpleTestCase');
445
446class LikeExpectation extends IdenticalExpectation {
447    function LikeExpectation($expectation) {
448        $expectation->_message = '';
449        $this->IdenticalExpectation($expectation);
450    }
451
452    function test($compare) {
453        $compare->_message = '';
454        return parent::test($compare);
455    }
456
457    function testMessage($compare) {
458        $compare->_message = '';
459        return parent::testMessage($compare);
460    }
461}
462
463class TestOfMockExpectations extends UnitTestCase {
464    var $test;
465
466    function setUp() {
467        $this->test = &new MockSimpleTestCase();
468    }
469
470    function &getMockedTest() {
471        return $this->test;
472    }
473
474    function testSettingExpectationOnNonMethodThrowsError() {
475        $mock = &new MockDummyWithInjectedTestCase();
476        $mock->expectMaximumCallCount('aMissingMethod', 2);
477        $this->assertError();
478    }
479
480    function testMaxCallsDetectsOverrun() {
481        $this->test->expectOnce('assert', array(
482                new LikeExpectation(new MaximumCallCountExpectation('aMethod', 2)),
483                3));
484        $mock = &new MockDummyWithInjectedTestCase();
485        $mock->expectMaximumCallCount('aMethod', 2);
486        $mock->aMethod();
487        $mock->aMethod();
488        $mock->aMethod();
489        $mock->_mock->atTestEnd('testSomething', $this->test);
490    }
491
492    function testTallyOnMaxCallsSendsPassOnUnderrun() {
493        $this->test->expectOnce('assert', array(
494                new LikeExpectation(new MaximumCallCountExpectation('aMethod', 2)),
495                2));
496        $mock = &new MockDummyWithInjectedTestCase();
497        $mock->expectMaximumCallCount("aMethod", 2);
498        $mock->aMethod();
499        $mock->aMethod();
500        $mock->_mock->atTestEnd('testSomething', $this->test);
501    }
502
503    function testExpectNeverDetectsOverrun() {
504        $this->test->expectOnce('assert', array(
505                new LikeExpectation(new MaximumCallCountExpectation('aMethod', 0)),
506                1));
507        $mock = &new MockDummyWithInjectedTestCase();
508        $mock->expectNever('aMethod');
509        $mock->aMethod();
510        $mock->_mock->atTestEnd('testSomething', $this->test);
511    }
512
513    function testTallyOnExpectNeverStillSendsPassOnUnderrun() {
514        $this->test->expectOnce('assert', array(
515                new LikeExpectation(new MaximumCallCountExpectation('aMethod', 0)),
516                0));
517        $mock = &new MockDummyWithInjectedTestCase();
518        $mock->expectNever('aMethod');
519        $mock->_mock->atTestEnd('testSomething', $this->test);
520    }
521
522    function testMinCalls() {
523        $this->test->expectOnce('assert', array(
524                new LikeExpectation(new MinimumCallCountExpectation('aMethod', 2)),
525                2));
526        $mock = &new MockDummyWithInjectedTestCase();
527        $mock->expectMinimumCallCount('aMethod', 2);
528        $mock->aMethod();
529        $mock->aMethod();
530        $mock->_mock->atTestEnd('testSomething', $this->test);
531    }
532
533    function testFailedNever() {
534        $this->test->expectOnce('assert', array(
535                new LikeExpectation(new MaximumCallCountExpectation('aMethod', 0)),
536                1));
537        $mock = &new MockDummyWithInjectedTestCase();
538        $mock->expectNever('aMethod');
539        $mock->aMethod();
540        $mock->_mock->atTestEnd('testSomething', $this->test);
541    }
542
543    function testUnderOnce() {
544        $this->test->expectOnce('assert', array(
545                new LikeExpectation(new CallCountExpectation('aMethod', 1)),
546                0));
547        $mock = &new MockDummyWithInjectedTestCase();
548        $mock->expectOnce('aMethod');
549        $mock->_mock->atTestEnd('testSomething', $this->test);
550    }
551
552    function testOverOnce() {
553        $this->test->expectOnce('assert', array(
554                new LikeExpectation(new CallCountExpectation('aMethod', 1)),
555                2));
556        $mock = &new MockDummyWithInjectedTestCase();
557        $mock->expectOnce('aMethod');
558        $mock->aMethod();
559        $mock->aMethod();
560        $mock->_mock->atTestEnd('testSomething', $this->test);
561    }
562
563    function testUnderAtLeastOnce() {
564        $this->test->expectOnce('assert', array(
565                new LikeExpectation(new MinimumCallCountExpectation('aMethod', 1)),
566                0));
567        $mock = &new MockDummyWithInjectedTestCase();
568        $mock->expectAtLeastOnce("aMethod");
569        $mock->_mock->atTestEnd('testSomething', $this->test);
570    }
571
572    function testZeroArguments() {
573        $this->test->expectOnce('assert', array(
574                new LikeExpectation(new ParametersExpectation(array())),
575                array(),
576                '*'));
577        $mock = &new MockDummyWithInjectedTestCase();
578        $mock->expect("aMethod", array());
579        $mock->aMethod();
580        $mock->_mock->atTestEnd('testSomething', $this->test);
581    }
582
583    function testExpectedArguments() {
584        $this->test->expectOnce('assert', array(
585                new LikeExpectation(new ParametersExpectation(array(1, 2, 3))),
586                array(1, 2, 3),
587                '*'));
588        $mock = &new MockDummyWithInjectedTestCase();
589        $mock->expect('aMethod', array(1, 2, 3));
590        $mock->aMethod(1, 2, 3);
591        $mock->_mock->atTestEnd('testSomething', $this->test);
592    }
593
594    function testFailedArguments() {
595        $this->test->expectOnce('assert', array(
596                new LikeExpectation(new ParametersExpectation(array('this'))),
597                array('that'),
598                '*'));
599        $mock = &new MockDummyWithInjectedTestCase();
600        $mock->expect('aMethod', array('this'));
601        $mock->aMethod('that');
602        $mock->_mock->atTestEnd('testSomething', $this->test);
603    }
604
605    function testWildcardsAreTranslatedToAnythingExpectations() {
606        $this->test->expectOnce('assert', array(
607                new LikeExpectation(new ParametersExpectation(array(
608                            new AnythingExpectation(), 123, new AnythingExpectation()))),
609                array(100, 123, 101),
610                '*'));
611        $mock = &new MockDummyWithInjectedTestCase($this);
612        $mock->expect("aMethod", array('*', 123, '*'));
613        $mock->aMethod(100, 123, 101);
614        $mock->_mock->atTestEnd('testSomething', $this->test);
615    }
616
617    function testSpecificPassingSequence() {
618        $this->test->expectAt(0, 'assert', array(
619                new LikeExpectation(new ParametersExpectation(array(1, 2, 3))),
620                array(1, 2, 3),
621                '*'));
622        $this->test->expectAt(1, 'assert', array(
623                new LikeExpectation(new ParametersExpectation(array('Hello'))),
624                array('Hello'),
625                '*'));
626        $mock = &new MockDummyWithInjectedTestCase();
627        $mock->expectAt(1, 'aMethod', array(1, 2, 3));
628        $mock->expectAt(2, 'aMethod', array('Hello'));
629        $mock->aMethod();
630        $mock->aMethod(1, 2, 3);
631        $mock->aMethod('Hello');
632        $mock->aMethod();
633        $mock->_mock->atTestEnd('testSomething', $this->test);
634    }
635
636    function testNonArrayForExpectedParametersGivesError() {
637        $mock = &new MockDummyWithInjectedTestCase();
638        $mock->expect("aMethod", "foo");
639        $this->assertErrorPattern('/\$args.*not an array/i');
640        $mock->aMethod();
641        $mock->tally();
642        $mock->_mock->atTestEnd('testSomething', $this->test);
643   }
644}
645
646class TestOfMockComparisons extends UnitTestCase {
647
648    function testEqualComparisonOfMocksDoesNotCrash() {
649        $expectation = &new EqualExpectation(new MockDummy());
650        $this->assertTrue($expectation->test(new MockDummy(), true));
651    }
652
653    function testIdenticalComparisonOfMocksDoesNotCrash() {
654        $expectation = &new IdenticalExpectation(new MockDummy());
655        $this->assertTrue($expectation->test(new MockDummy()));
656    }
657}
658
659class ClassWithSpecialMethods {
660    function __get($name) { }
661    function __set($name, $value) { }
662    function __isset($name) { }
663    function __unset($name) { }
664    function __call($method, $arguments) { }
665    function __toString() { }
666}
667Mock::generate('ClassWithSpecialMethods');
668
669class TestOfSpecialMethods extends UnitTestCase {
670    function skip() {
671        $this->skipIf(version_compare(phpversion(), '5', '<='), 'Overloading not tested unless PHP 5+');
672    }
673
674    function testCanMockTheThingAtAll() {
675        $mock = new MockClassWithSpecialMethods();
676    }
677
678    function testReturnFromSpecialAccessor() {
679        $mock = &new MockClassWithSpecialMethods();
680        $mock->setReturnValue('__get', '1st Return', array('first'));
681        $mock->setReturnValue('__get', '2nd Return', array('second'));
682        $this->assertEqual($mock->first, '1st Return');
683        $this->assertEqual($mock->second, '2nd Return');
684    }
685
686    function testcanExpectTheSettingOfValue() {
687        $mock = &new MockClassWithSpecialMethods();
688        $mock->expectOnce('__set', array('a', 'A'));
689        $mock->a = 'A';
690    }
691
692    function testCanSimulateAnOverloadmethod() {
693        $mock = &new MockClassWithSpecialMethods();
694        $mock->expectOnce('__call', array('amOverloaded', array('A')));
695        $mock->setReturnValue('__call', 'aaa');
696        $this->assertIdentical($mock->amOverloaded('A'), 'aaa');
697    }
698
699    function testCanEmulateIsset() {
700        $mock = &new MockClassWithSpecialMethods();
701        $mock->setReturnValue('__isset', true);
702        $this->assertIdentical(isset($mock->a), true);
703    }
704
705    function testCanExpectUnset() {
706        $mock = &new MockClassWithSpecialMethods();
707        $mock->expectOnce('__unset', array('a'));
708        unset($mock->a);
709    }
710
711    function testToStringMagic() {
712        $mock = &new MockClassWithSpecialMethods();
713        $mock->expectOnce('__toString');
714        $mock->setReturnValue('__toString', 'AAA');
715        ob_start();
716        print $mock;
717        $output = ob_get_contents();
718        ob_end_clean();
719        $this->assertEqual($output, 'AAA');
720    }
721}
722
723if (version_compare(phpversion(), '5', '>=')) {
724    $class  = 'class WithStaticMethod { ';
725    $class .= '    static function aStaticMethod() { } ';
726    $class .= '}';
727    eval($class);
728}
729Mock::generate('WithStaticMethod');
730
731class TestOfMockingClassesWithStaticMethods extends UnitTestCase {
732    function skip() {
733        $this->skipUnless(version_compare(phpversion(), '5', '>='), 'Static methods not tested unless PHP 5+');
734    }
735    
736    function testStaticMethodIsMockedAsStatic() {
737        $mock = new WithStaticMethod();
738        $reflection = new ReflectionClass($mock);
739        $method = $reflection->getMethod('aStaticMethod');
740        $this->assertTrue($method->isStatic());
741    }
742}
743
744if (version_compare(phpversion(), '5', '>=')) {
745    class MockTestException extends Exception { }
746}
747
748class TestOfThrowingExceptionsFromMocks extends UnitTestCase {
749    function skip() {
750        $this->skipUnless(version_compare(phpversion(), '5', '>='), 'Exception throwing not tested unless PHP 5+');
751    }
752
753    function testCanThrowOnMethodCall() {
754        $mock = new MockDummy();
755        $mock->throwOn('aMethod');
756        $this->expectException();
757        $mock->aMethod();
758    }
759
760    function testCanThrowSpecificExceptionOnMethodCall() {
761        $mock = new MockDummy();
762        $mock->throwOn('aMethod', new MockTestException());
763        $this->expectException();
764        $mock->aMethod();
765    }
766    
767    function testThrowsOnlyWhenCallSignatureMatches() {
768        $mock = new MockDummy();
769        $mock->throwOn('aMethod', new MockTestException(), array(3));
770        $mock->aMethod(1);
771        $mock->aMethod(2);
772        $this->expectException();
773        $mock->aMethod(3);
774    }
775    
776    function testCanThrowOnParticularInvocation() {
777        $mock = new MockDummy();
778        $mock->throwAt(2, 'aMethod', new MockTestException());
779        $mock->aMethod();
780        $mock->aMethod();
781        $this->expectException();
782        $mock->aMethod();
783    }
784}
785
786class TestOfThrowingErrorsFromMocks extends UnitTestCase {
787    
788    function testCanGenerateErrorFromMethodCall() {
789        $mock = new MockDummy();
790        $mock->errorOn('aMethod', 'Ouch!');
791        $this->expectError('Ouch!');
792        $mock->aMethod();
793    }
794    
795    function testGeneratesErrorOnlyWhenCallSignatureMatches() {
796        $mock = new MockDummy();
797        $mock->errorOn('aMethod', 'Ouch!', array(3));
798        $mock->aMethod(1);
799        $mock->aMethod(2);
800        $this->expectError();
801        $mock->aMethod(3);
802    }
803    
804    function testCanGenerateErrorOnParticularInvocation() {
805        $mock = new MockDummy();
806        $mock->errorAt(2, 'aMethod', 'Ouch!');
807        $mock->aMethod();
808        $mock->aMethod();
809        $this->expectError();
810        $mock->aMethod();
811    }
812}
813
814Mock::generatePartial('Dummy', 'TestDummy', array('anotherMethod'));
815
816class TestOfPartialMocks extends UnitTestCase {
817
818    function testMethodReplacementWithNoBehaviourReturnsNull() {
819        $mock = &new TestDummy();
820        $this->assertEqual($mock->aMethod(99), 99);
821        $this->assertNull($mock->anotherMethod());
822    }
823
824    function testSettingReturns() {
825        $mock = &new TestDummy();
826        $mock->setReturnValue('anotherMethod', 33, array(3));
827        $mock->setReturnValue('anotherMethod', 22);
828        $mock->setReturnValueAt(2, 'anotherMethod', 44, array(3));
829        $this->assertEqual($mock->anotherMethod(), 22);
830        $this->assertEqual($mock->anotherMethod(3), 33);
831        $this->assertEqual($mock->anotherMethod(3), 44);
832    }
833
834    function testReferences() {
835        $mock = &new TestDummy();
836        $object = new Dummy();
837        $mock->setReturnReferenceAt(0, 'anotherMethod', $object, array(3));
838        $this->assertReference($zref =& $mock->anotherMethod(3), $object);
839    }
840
841    function testExpectations() {
842        $mock = &new TestDummy();
843        $mock->expectCallCount('anotherMethod', 2);
844        $mock->expect('anotherMethod', array(77));
845        $mock->expectAt(1, 'anotherMethod', array(66));
846        $mock->anotherMethod(77);
847        $mock->anotherMethod(66);
848    }
849
850    function testSettingExpectationOnMissingMethodThrowsError() {
851        $mock = &new TestDummy();
852        $mock->expectCallCount('aMissingMethod', 2);
853        $this->assertError();
854    }
855}
856
857class ConstructorSuperClass {
858    function ConstructorSuperClass() { }
859}
860
861class ConstructorSubClass extends ConstructorSuperClass {
862}
863
864class TestOfPHP4StyleSuperClassConstruct extends UnitTestCase {
865    /*
866     * This addresses issue #1231401.  Without the fix in place, this will
867     * generate a fatal PHP error.
868     */
869    function testBasicConstruct() {
870        Mock::generate('ConstructorSubClass');
871        $mock = &new MockConstructorSubClass();
872        $this->assertIsA($mock, 'ConstructorSubClass');
873        $this->assertTrue(method_exists($mock, 'ConstructorSuperClass'));
874    }
875}
876
877class TestOfPHP5StaticMethodMocking extends UnitTestCase {
878    function skip() {
879        $this->skipIf(version_compare(phpversion(), '5', '<='), 'Static methods not tested unless PHP 5+');
880    }
881
882    function testCanCreateAMockObjectWithStaticMethodsWithoutError() {
883        eval('
884            class SimpleObjectContainingStaticMethod {
885                static function someStatic() { }
886            }
887        ');
888
889        Mock::generate('SimpleObjectContainingStaticMethod');
890        $this->assertNoErrors();
891    }
892}
893
894class TestOfPHP5AbstractMethodMocking extends UnitTestCase {
895    function skip() {
896        $this->skipIf(version_compare(phpversion(), '5', '<='), 'Abstract class/methods not tested unless PHP 5+');
897    }
898
899    function testCanCreateAMockObjectFromAnAbstractWithProperFunctionDeclarations() {
900        eval('
901             abstract class SimpleAbstractClassContainingAbstractMethods {
902                abstract function anAbstract();
903                abstract function anAbstractWithParameter($foo);
904                abstract function anAbstractWithMultipleParameters($foo, $bar);
905            }
906        ');
907
908        Mock::generate('SimpleAbstractClassContainingAbstractMethods');
909        $this->assertNoErrors();
910
911        $this->assertTrue(
912            method_exists(
913                'MockSimpleAbstractClassContainingAbstractMethods',
914                'anAbstract'
915            )
916        );
917        $this->assertTrue(
918            method_exists(
919                'MockSimpleAbstractClassContainingAbstractMethods',
920                'anAbstractWithParameter'
921            )
922        );
923        $this->assertTrue(
924            method_exists(
925                'MockSimpleAbstractClassContainingAbstractMethods',
926                'anAbstractWithMultipleParameters'
927            )
928        );
929    }
930
931    function testMethodsDefinedAsAbstractInParentShouldHaveFullSignature() {
932        eval('
933             abstract class SimpleParentAbstractClassContainingAbstractMethods {
934                abstract function anAbstract();
935                abstract function anAbstractWithParameter($foo);
936                abstract function anAbstractWithMultipleParameters($foo, $bar);
937            }
938
939             class SimpleChildAbstractClassContainingAbstractMethods extends SimpleParentAbstractClassContainingAbstractMethods {
940                function anAbstract(){}
941                function anAbstractWithParameter($foo){}
942                function anAbstractWithMultipleParameters($foo, $bar){}
943            }
944
945            class EvenDeeperEmptyChildClass extends SimpleChildAbstractClassContainingAbstractMethods {}
946        ');
947
948        Mock::generate('SimpleChildAbstractClassContainingAbstractMethods');
949        $this->assertNoErrors();
950
951        $this->assertTrue(
952            method_exists(
953                'MockSimpleChildAbstractClassContainingAbstractMethods',
954                'anAbstract'
955            )
956        );
957        $this->assertTrue(
958            method_exists(
959                'MockSimpleChildAbstractClassContainingAbstractMethods',
960                'anAbstractWithParameter'
961            )
962        );
963        $this->assertTrue(
964            method_exists(
965                'MockSimpleChildAbstractClassContainingAbstractMethods',
966                'anAbstractWithMultipleParameters'
967            )
968        );
969        
970        Mock::generate('EvenDeeperEmptyChildClass');
971        $this->assertNoErrors();
972
973        $this->assertTrue(
974            method_exists(
975                'MockEvenDeeperEmptyChildClass',
976                'anAbstract'
977            )
978        );
979        $this->assertTrue(
980            method_exists(
981                'MockEvenDeeperEmptyChildClass',
982                'anAbstractWithParameter'
983            )
984        );
985        $this->assertTrue(
986            method_exists(
987                'MockEvenDeeperEmptyChildClass',
988                'anAbstractWithMultipleParameters'
989            )
990        );
991    }
992}
993
994?>