diff --git a/src/Microsoft.AspNetCore.SignalR.Client/HubConnection.cs b/src/Microsoft.AspNetCore.SignalR.Client/HubConnection.cs index 63dd2b2260..de3aaca1b9 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client/HubConnection.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client/HubConnection.cs @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.SignalR.Client { if (_connectionActive.IsCancellationRequested) { - throw new InvalidOperationException("Connection has been terminated"); + throw new InvalidOperationException("Connection has been terminated."); } _pendingCalls.Add(descriptor.Id, irq); } @@ -185,11 +185,11 @@ namespace Microsoft.AspNetCore.SignalR.Client { if (ex != null) { - call.Completion.TrySetCanceled(); + call.Completion.TrySetException(ex); } else { - call.Completion.TrySetException(ex); + call.Completion.TrySetCanceled(); } } _pendingCalls.Clear(); diff --git a/test/Microsoft.AspNetCore.Sockets.Client.Tests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.Sockets.Client.Tests/HubConnectionTests.cs index 09fe12c0e9..0e385da6db 100644 --- a/test/Microsoft.AspNetCore.Sockets.Client.Tests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.Sockets.Client.Tests/HubConnectionTests.cs @@ -108,8 +108,6 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests Assert.Equal("Cannot invoke methods on disposed connections.", exception.Message); } - // TODO: If HubConnection takes (I)Connection we could just tests if events are wired up - [Fact] public async Task HubConnectionConnectedEventRaisedWhenTheClientIsConnected() { @@ -167,5 +165,62 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests Assert.Null(await closedEventTcs.Task.OrTimeout()); } } + + [Fact] + public async Task CannotCallInvokeOnClosedHubConnection() + { + var mockConnection = new Mock(); + mockConnection + .Setup(m => m.DisposeAsync()) + .Callback(() => mockConnection.Raise(c => c.Closed += null, (Exception)null)) + .Returns(Task.FromResult(null)); + + var hubConnection = new HubConnection(mockConnection.Object, Mock.Of(), new LoggerFactory()); + + await hubConnection.StartAsync(Mock.Of()); + await hubConnection.DisposeAsync(); + var exception = await Assert.ThrowsAsync( + async () => await hubConnection.Invoke("test", typeof(int))); + + Assert.Equal("Connection has been terminated.", exception.Message); + } + + [Fact] + public async Task PendingInvocationsAreCancelledWhenConnectionClosesCleanly() + { + var mockConnection = new Mock(); + mockConnection + .Setup(m => m.DisposeAsync()) + .Callback(() => mockConnection.Raise(c => c.Closed += null, (Exception)null)) + .Returns(Task.FromResult(null)); + + var hubConnection = new HubConnection(mockConnection.Object, Mock.Of(), new LoggerFactory()); + + await hubConnection.StartAsync(Mock.Of()); + var invokeTask = hubConnection.Invoke("testMethod", typeof(int)); + await hubConnection.DisposeAsync(); + + await Assert.ThrowsAsync(async () => await invokeTask); + } + + [Fact] + public async Task PendingInvocationsAreTerminatedWithExceptionWhenConnectionClosesDueToError() + { + var exception = new InvalidOperationException(); + var mockConnection = new Mock(); + mockConnection + .Setup(m => m.DisposeAsync()) + .Callback(() => mockConnection.Raise(c => c.Closed += null, exception)) + .Returns(Task.FromResult(null)); + + var hubConnection = new HubConnection(mockConnection.Object, Mock.Of(), new LoggerFactory()); + + await hubConnection.StartAsync(Mock.Of()); + var invokeTask = hubConnection.Invoke("testMethod", typeof(int)); + await hubConnection.DisposeAsync(); + + var thrown = await Assert.ThrowsAsync(exception.GetType(), async () => await invokeTask); + Assert.Same(exception, thrown); + } } }