Skip to content

Commit fe15af7

Browse files
martinsikmbonneau
authored andcommitted
Testing higher-order Observables (#144)
* enable testing higher-order observables * refactored into onNext * remove redundant argument in OnNextObservableNotification * cleanup * make sure automatic subscriptions aren't logged
1 parent f913b94 commit fe15af7

File tree

7 files changed

+332
-16
lines changed

7 files changed

+332
-16
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Rx\Notification;
4+
5+
use Rx\Observable;
6+
use Rx\Testing\MockHigherOrderObserver;
7+
use Rx\Testing\TestScheduler;
8+
9+
class OnNextObservableNotification extends OnNextNotification
10+
{
11+
/** @var MockHigherOrderObserver */
12+
private $observer;
13+
14+
public function __construct($value, TestScheduler $scheduler = null)
15+
{
16+
parent::__construct($value);
17+
if (!$scheduler) {
18+
$scheduler = new TestScheduler();
19+
}
20+
21+
$this->observer = new MockHigherOrderObserver($scheduler, $scheduler->getClock());
22+
23+
/** @var Observable $value */
24+
$value->subscribe($this->observer, $scheduler);
25+
26+
$scheduler->start();
27+
}
28+
29+
public function equals($other)
30+
{
31+
$messages1 = $this->getMessages();
32+
/** @var OnNextObservableNotification $other */
33+
$messages2 = $other->getMessages();
34+
35+
if (count($messages1) != count($messages2)) {
36+
return false;
37+
}
38+
39+
for ($i = 0; $i < count($messages1); $i++) {
40+
if (!$messages1[$i]->equals($messages2[$i])) {
41+
return false;
42+
}
43+
}
44+
45+
return true;
46+
}
47+
48+
public function getMessages()
49+
{
50+
return $this->observer->getMessages();
51+
}
52+
53+
public function __toString()
54+
{
55+
return '[' . join(', ', $this->getMessages()) . ']';
56+
}
57+
}

lib/Rx/Testing/ColdObservable.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ public function __construct($scheduler, $messages = [])
2222

2323
public function subscribe(ObserverInterface $observer, $scheduler = null)
2424
{
25-
$this->subscriptions[] = new Subscription($this->scheduler->getClock());
26-
$index = count($this->subscriptions) - 1;
27-
25+
$scheduler = $scheduler ?: $this->scheduler;
2826
$currentObservable = $this;
2927
$disposable = new CompositeDisposable();
30-
$scheduler = $this->scheduler;
3128
$isDisposed = false;
29+
$index = null;
30+
31+
if (!($observer instanceof MockHigherOrderObserver)) {
32+
$this->subscriptions[] = new Subscription($scheduler->getClock());
33+
$index = count($this->subscriptions) - 1;
34+
}
3235

3336
foreach ($this->messages as $message) {
3437
$notification = $message->getValue();
@@ -50,7 +53,9 @@ public function subscribe(ObserverInterface $observer, $scheduler = null)
5053

5154
return new CallbackDisposable(function () use (&$currentObservable, $index, $observer, $scheduler, &$subscriptions, &$isDisposed) {
5255
$isDisposed = true;
53-
$subscriptions[$index] = new Subscription($subscriptions[$index]->getSubscribed(), $scheduler->getClock());
56+
if (!($observer instanceof MockHigherOrderObserver)) {
57+
$subscriptions[$index] = new Subscription($subscriptions[$index]->getSubscribed(), $scheduler->getClock());
58+
}
5459
});
5560

5661
}

lib/Rx/Testing/HotObservable.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,22 @@ public function subscribe(ObserverInterface $observer, $scheduler = null)
4343
{
4444
$currentObservable = $this;
4545

46-
$this->observers[] = $observer;
47-
$this->subscriptions[] = new Subscription($this->scheduler->getClock());
46+
$this->observers[] = $observer;
47+
$subscriptions = &$this->subscriptions;
48+
$index = null;
4849

49-
$subscriptions = &$this->subscriptions;
50+
if (!($observer instanceof MockHigherOrderObserver)) {
51+
$this->subscriptions[] = new Subscription($this->scheduler->getClock());
52+
$index = count($this->subscriptions) - 1;
53+
}
5054

51-
$index = count($this->subscriptions) - 1;
5255
$scheduler = $this->scheduler;
5356

5457
return new CallbackDisposable(function () use (&$currentObservable, $index, $observer, $scheduler, &$subscriptions) {
5558
$currentObservable->removeObserver($observer);
56-
$subscriptions[$index] = new Subscription($subscriptions[$index]->getSubscribed(), $scheduler->getClock());
59+
if (!($observer instanceof MockHigherOrderObserver)) {
60+
$subscriptions[$index] = new Subscription($subscriptions[$index]->getSubscribed(), $scheduler->getClock());
61+
}
5762
});
5863
}
5964

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Rx\Testing;
4+
5+
class MockHigherOrderObserver extends MockObserver
6+
{
7+
}

lib/Rx/Testing/MockObserver.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,55 @@
66
use Rx\Notification\OnCompletedNotification;
77
use Rx\Notification\OnErrorNotification;
88
use Rx\Notification\OnNextNotification;
9+
use Rx\Notification\OnNextObservableNotification;
10+
use Rx\Observable;
911
use Rx\ObserverInterface;
1012

1113
/**
1214
* Mock observer that records all messages.
1315
*/
1416
class MockObserver implements ObserverInterface
1517
{
18+
/** @var TestScheduler */
1619
private $scheduler;
20+
21+
/** @var Recorded[] */
1722
private $messages = [];
1823

19-
public function __construct($scheduler)
24+
private $startTime = 0;
25+
26+
public function __construct($scheduler, $startTime = 0)
2027
{
2128
$this->scheduler = $scheduler;
29+
$this->startTime = $startTime;
2230
}
2331

2432
public function onNext($value)
2533
{
34+
if ($value instanceof Observable) {
35+
$notification = new OnNextObservableNotification($value, $this->scheduler);
36+
} else {
37+
$notification = new OnNextNotification($value);
38+
}
39+
2640
$this->messages[] = new Recorded(
27-
$this->scheduler->getClock(),
28-
new OnNextNotification($value)
41+
$this->scheduler->getClock() - $this->startTime,
42+
$notification
2943
);
3044
}
3145

3246
public function onError(Exception $error)
3347
{
3448
$this->messages[] = new Recorded(
35-
$this->scheduler->getClock(),
49+
$this->scheduler->getClock() - $this->startTime,
3650
new OnErrorNotification($error)
3751
);
3852
}
3953

4054
public function onCompleted()
4155
{
4256
$this->messages[] = new Recorded(
43-
$this->scheduler->getClock(),
57+
$this->scheduler->getClock() - $this->startTime,
4458
new OnCompletedNotification()
4559
);
4660
}

0 commit comments

Comments
 (0)