I use Moq 4.18.2 framework for my tests.
The RtspClient
might throw an OperationCanceledException
from ConnectAsync
. So, I try to test this scenario. My test below throws an exception System.OperationCanceledException: The operation was canceled.
and the catch (OperationCanceledException)
never gets executed. What am I doing wrong here?
RTSP
public interface IRtspClient : IDisposable
{
event EventHandler<RawFrame> FrameReceived;
Task ConnectAsync(CancellationToken token);
Task ReceiveAsync(CancellationToken token);
}
Method that uses IRtspClient
public async Task ConnectAsync(CancellationToken token = default)
{
try
{
await _rtspClient.ConnectAsync(token).ConfigureAwait(false);
OnConnected();
}
catch (OperationCanceledException ex)
{
OnConnectAttemptCanceled(ex);
throw;
}
catch(Exception ex)
{
OnFailedToConnect(ex);
throw;
}
}
Test
[TestMethod]
public async Task ConnectAsync_Canceled()
{
var expectedCanceledTaskStatus = true;
var tcs = new CancellationTokenSource();
tcs.Cancel();
var rtspClient = new Mock<IRtspClient>();
rtspClient
.Setup(_ => _.ConnectAsync(It.IsAny<CancellationToken>()))
.Returns(Task.FromException<OperationCanceledException>(new OperationCanceledException()))
var actualCanceledTaskStatus = false;
var camera = new MyCamera(rtspClient.Object);
camera.FailedToConnect += () => actualCanceledTaskStatus = true;
await camera.ConnectAsync(tcs.Token);
Assert.AreEqual(expectedCanceledTaskStatus, actualCanceledTaskStatus);
}
UPDATE Added missing await
as suggested by @Dai, but my test still fails. Can anyone take a look at the test code?
await
the returned Task
inside the try{}
block - otherwise synchronous control will immediately leave the try{}
block.delegate()
local) will not be caught by the catch
.CancellationTokenSource
is IDisposable
, so you should change your ConnectAsync_Canceled
test to wrap it in a using()
block.Change your code to this:
public async Task ConnectAsync( CancellationToken cancellationToken = default )
{
try
{
await this.rtspClient.ConnectAsync(cancellationToken ).ConfigureAwait(false);
this.OnConnected();
}
catch( OperationCanceledException cEx )
{
this.OnConnectAttemptCanceled( cEx );
throw; // Re-throw so the `Task` representing *this method* (`ConnectAsync`) will report as Cancelled rather than Succeeded.
}
catch( Exception ex )
{
this.OnFailedToConnect( ex );
throw; // Re-throw so the `Task` representing *this method* (`ConnectAsync`) will report as Failed rather than Succeeded.
}
}
I found my mistake (in addition to what @Dai noticed). I should have either put await camera.ConnectAsync
from my test in try-catch
or used Assert.ThrowsExceptionAsync
. I chose the latter. Here is the working test:
[TestMethod]
public async Task ConnectAsync_Canceled()
{
var expectedTaskCanceledStatus = true;
var rtspClient = new Mock<IRtspClient>();
rtspClient
.Setup(_ => _.ConnectAsync(default(CancellationToken)))
.Returns(Task.FromException(new OperationCanceledException()));
var actualTaskCanceledStatus = false;
var camera = new MyCamera(rtspClient.Object);
camera.ConnectAttemptCanceled += () => actualTaskCanceledStatus = true;
await Assert.ThrowsExceptionAsync<OperationCanceledException>(async () => await camera.ConnectAsync());
Assert.AreEqual(expectedTaskCanceledStatus, actualTaskCanceledStatus);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.