PageRenderTime 250ms CodeModel.GetById 81ms app.highlight 111ms RepoModel.GetById 49ms app.codeStats 1ms

/tests/simpletest/test/mock_objects_test.php

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