-
Notifications
You must be signed in to change notification settings - Fork 135
Refactor observable tester #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
a4a6cd3
use FluentTestObserver to test subscriptions
rose-a 31f6988
fix assertion fail messages
rose-a 650352a
consolidate dependencies
rose-a 9b745f0
Apply suggestions from code review
rose-a e67d70e
remove unused file, cleanup GitVersionTask references
rose-a 3724956
add async assertions
rose-a 93c1f07
run observable assertions async
rose-a c06cb6e
move assertion outside of try..catch
rose-a 30c249c
set default timeout to 10s
rose-a 9e676eb
consolidate ObservableExtensions and ObservableAssertions
rose-a e3606c2
fix Assertion messages, add doc comments
rose-a 0145514
optimize assertion message for push assertions
rose-a c8f2570
fix assertion message again
rose-a b19f627
and again
rose-a ba7a991
fix condition
rose-a feb2362
update reactive assertions
rose-a ccdf82d
fix bug in FluentTestObserver
rose-a d1950f8
fix for issue #87
rose-a File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
] | ||
}, | ||
"gitversion.tool": { | ||
"version": "5.1.3", | ||
"version": "5.2.4", | ||
"commands": [ | ||
"dotnet-gitversion" | ||
] | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
src/GraphQL.Client.Serializer.SystemTextJson/GraphQL.Client.Serializer.SystemTextJson.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
tests/GraphQL.Client.Tests.Common/FluentAssertions.Reactive/FluentTestObserver.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Reactive; | ||
using System.Reactive.Concurrency; | ||
using System.Reactive.Disposables; | ||
using System.Reactive.Linq; | ||
using Microsoft.Reactive.Testing; | ||
|
||
namespace GraphQL.Client.Tests.Common.FluentAssertions.Reactive | ||
{ | ||
/// <summary> | ||
/// Observer for testing <see cref="Observable"/>s using the FluentAssertions framework | ||
/// </summary> | ||
/// <typeparam name="TPayload"></typeparam> | ||
public class FluentTestObserver<TPayload> : IObserver<TPayload>, IDisposable | ||
{ | ||
private readonly IDisposable _subscription; | ||
private readonly IScheduler _observeScheduler; | ||
private readonly RollingReplaySubject<Recorded<Notification<TPayload>>> _rollingReplaySubject = new RollingReplaySubject<Recorded<Notification<TPayload>>>(); | ||
|
||
/// <summary> | ||
/// The observable which is observed by this instance | ||
/// </summary> | ||
public IObservable<TPayload> Subject { get; } | ||
|
||
/// <summary> | ||
/// The stream of recorded <see cref="Notification{T}"/>s | ||
/// </summary> | ||
public IObservable<Recorded<Notification<TPayload>>> RecordedNotificationStream => _rollingReplaySubject.AsObservable(); | ||
|
||
/// <summary> | ||
/// The recorded <see cref="Notification{T}"/>s | ||
/// </summary> | ||
public IEnumerable<Recorded<Notification<TPayload>>> RecordedNotifications => | ||
_rollingReplaySubject.GetSnapshot(); | ||
|
||
/// <summary> | ||
/// The recorded messages | ||
/// </summary> | ||
public IEnumerable<TPayload> RecordedMessages => | ||
RecordedNotifications.GetMessages(); | ||
|
||
/// <summary> | ||
/// The exception | ||
/// </summary> | ||
public Exception Error => | ||
RecordedNotifications | ||
.Where(r => r.Value.Kind == NotificationKind.OnError) | ||
.Select(r => r.Value.Exception) | ||
.FirstOrDefault(); | ||
|
||
/// <summary> | ||
/// The recorded messages | ||
/// </summary> | ||
public bool Completed => | ||
RecordedNotifications | ||
.Any(r => r.Value.Kind == NotificationKind.OnCompleted); | ||
|
||
/// <summary> | ||
/// Creates a new <see cref="FluentTestObserver{TPayload}"/> which subscribes to the supplied <see cref="IObservable{T}"/> | ||
/// </summary> | ||
/// <param name="subject">the <see cref="IObservable{T}"/> under test</param> | ||
public FluentTestObserver(IObservable<TPayload> subject) | ||
{ | ||
Subject = subject; | ||
_observeScheduler = new EventLoopScheduler(); | ||
_subscription = subject.ObserveOn(_observeScheduler).Subscribe(this); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a new <see cref="FluentTestObserver{TPayload}"/> which subscribes to the supplied <see cref="IObservable{T}"/> | ||
/// </summary> | ||
/// <param name="subject">the <see cref="IObservable{T}"/> under test</param> | ||
public FluentTestObserver(IObservable<TPayload> subject, IScheduler scheduler) | ||
{ | ||
Subject = subject; | ||
_observeScheduler = scheduler; | ||
_subscription = subject.ObserveOn(scheduler).Subscribe(this); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a new <see cref="FluentTestObserver{TPayload}"/> which subscribes to the supplied <see cref="IObservable{T}"/> | ||
/// </summary> | ||
/// <param name="subject">the <see cref="IObservable{T}"/> under test</param> | ||
public FluentTestObserver(IObservable<TPayload> subject, TestScheduler testScheduler) | ||
{ | ||
Subject = subject; | ||
_observeScheduler = testScheduler; | ||
_subscription = subject.ObserveOn(Scheduler.CurrentThread).Subscribe(this); | ||
} | ||
|
||
/// <summary> | ||
/// Clears the recorded notifications and messages as well as the recorded notifications stream buffer | ||
/// </summary> | ||
public void Clear() => _rollingReplaySubject.Clear(); | ||
|
||
/// <inheritdoc /> | ||
public void OnNext(TPayload value) => | ||
_rollingReplaySubject.OnNext(new Recorded<Notification<TPayload>>(_observeScheduler.Now.UtcTicks, Notification.CreateOnNext(value))); | ||
|
||
/// <inheritdoc /> | ||
public void OnError(Exception exception) => | ||
_rollingReplaySubject.OnNext(new Recorded<Notification<TPayload>>(_observeScheduler.Now.UtcTicks, Notification.CreateOnError<TPayload>(exception))); | ||
|
||
/// <inheritdoc /> | ||
public void OnCompleted() => | ||
_rollingReplaySubject.OnNext(new Recorded<Notification<TPayload>>(_observeScheduler.Now.UtcTicks, Notification.CreateOnCompleted<TPayload>())); | ||
rose-a marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// <inheritdoc /> | ||
public void Dispose() | ||
{ | ||
_subscription?.Dispose(); | ||
_rollingReplaySubject?.Dispose(); | ||
} | ||
|
||
/// <summary> | ||
/// Returns an <see cref="ReactiveAssertions{TPayload}"/> object that can be used to assert the observed <see cref="IObservable{T}"/> | ||
/// </summary> | ||
/// <returns></returns> | ||
public ReactiveAssertions<TPayload> Should() => new ReactiveAssertions<TPayload>(this); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
tests/GraphQL.Client.Tests.Common/FluentAssertions.Reactive/NoSynchronizationContextScope.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace GraphQL.Client.Tests.Common.FluentAssertions.Reactive | ||
{ | ||
internal static class NoSynchronizationContextScope | ||
{ | ||
public static T ExecuteInDefaultSynchronizationContext<T>(this Task<T> task) | ||
{ | ||
using (NoSynchronizationContextScope.Enter()) | ||
{ | ||
task.Wait(); | ||
return task.Result; | ||
} | ||
} | ||
|
||
public static DisposingAction Enter() | ||
{ | ||
var context = SynchronizationContext.Current; | ||
SynchronizationContext.SetSynchronizationContext(null); | ||
return new DisposingAction(() => SynchronizationContext.SetSynchronizationContext(context)); | ||
} | ||
|
||
internal class DisposingAction : IDisposable | ||
{ | ||
private readonly Action action; | ||
|
||
public DisposingAction(Action action) | ||
{ | ||
this.action = action; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
action(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.