Getting Started
The easiest way to get started using FSharp.Control.Reactive is to take a look at the tests. In general, you can consider the Observable
module as providing a set of extensions to the built-in Observable
module.
Observable Module
As a first, simple example, the built-in module does not include a zip
operator, but FSharp.Control.Reactive fills in this gap:
1: 2: 3: 4: 5: 6: 7: 8: |
|
Computation Expressions
The provided computation expressions open new approaches for constructing and combining Observable
computations. The observe
computation expression provides a simple workflow using the essential LINQ operators:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
You can find a few additional examples of both the observe
and rxquery
computation expressions on the source blog post.
Reactive Extensions
For more information on Rx, check out the Rx Workshop on Channel 9. The examples provided in the workshop should be easy to port to FSharp.Control.Reactive. The Beginner's Guide to the Reactive Extensions includes many other links to excellent content.
Reactive Testing
The Rx.NET has several OOP-minded objects to test Reactive Applications. This package contains some wrappers to make your Reactive Tests more functional.
Following test shows how the Broadcast Subject can be tested:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: |
|
- The
TestSchedule.usage
call wil make sure we have a virtual time scheduler that we can use to sync our different observables and observers. - The
subscribeTestObserver
call will subscribe the givenobservable
to aTestObserver
. - This
TestObserver
can be used to assert on the emits that the SUT sends to it by using theTesteObserver
module. (TestObserver.nexts
,TestObserver.all
,TestObserver.errors
)
The testing package also contains generated TestNotifications
which we can use to simulate a stream of emits.
This values has to be registered first before using.
Following example shows how the Functor Law can be testsd by creating a Hot Observable of simulated emits.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: |
|
NOTE: the previous test contains a Observable.retry
call because the simulated emits will possible contain 'OnError' emits as well.
See: https://github.com/fsprojects/FSharp.Control.Reactive/blob/master/src/FSharp.Control.Reactive.Testing/TestNotifications.fs for more info on how the simulated emits are generated.
namespace FSharp
--------------------
namespace Microsoft.FSharp
namespace FSharp.Control
--------------------
namespace Microsoft.FSharp.Control
module Observable
from FSharp.Control.Reactive
--------------------
module Observable
from Microsoft.FSharp.Control
val subscribe : onNext:('T -> unit) -> observable:System.IObservable<'T> -> System.IDisposable
--------------------
val subscribe : callback:('T -> unit) -> source:System.IObservable<'T> -> System.IDisposable
from FSharp.Control.Reactive
type TestAttribute =
inherit NUnitAttribute
new : unit -> TestAttribute
member ApplyToTest : test:Test -> unit
member Author : string with get, set
member BuildFrom : method:IMethodInfo * suite:Test -> TestMethod
member Description : string with get, set
member ExpectedResult : obj with get, set
member TestOf : Type with get, set
--------------------
TestAttribute() : TestAttribute
static member All : config:Config -> unit
static member All : config:Config * test:Type -> unit
static member Method : config:Config * methodInfo:MethodInfo * ?target:obj -> unit
static member One : config:Config * property:'Testable -> unit
static member One : name:string * config:Config * property:'Testable -> unit
static member Quick : property:'Testable -> unit
static member Quick : name:string * property:'Testable -> unit
static member QuickAll : unit -> unit
static member QuickAll : test:Type -> unit
static member QuickThrowOnFailure : property:'Testable -> unit
...
val int : value:'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
from FSharp.Control.Reactive.Testing
module Subject
from FSharp.Control.Reactive
--------------------
type Subject<'a> =
private new : unit -> Subject<'a>
static member behavior : x:'a -> BehaviorSubject<'a>
static member async : AsyncSubject<'a>
static member broadcast : Subject<'a>
static member replay : ReplaySubject<'a>
from FSharp.Control.Reactive.Testing
type SetUpAttribute =
inherit NUnitAttribute
new : unit -> SetUpAttribute
--------------------
SetUpAttribute() : SetUpAttribute
from FsCheck
static member GenNotifications : unit -> Arbitrary<TestNotifications<'a>>
union case TestNotifications.TestNotifications: TestNotification<'a> list -> TestNotifications<'a>
--------------------
type TestNotifications<'a> = | TestNotifications of TestNotification<'a> list
val map : f:('a -> 'b) -> source:System.IObservable<'a> -> System.IObservable<'b>
--------------------
val map : mapping:('T -> 'U) -> source:System.IObservable<'T> -> System.IObservable<'U>
module TestNotification
from FSharp.Control.Reactive.Testing
--------------------
type TestNotification<'a> = Reactive.Testing.Recorded<System.Reactive.Notification<'a>>