我使用Moq4.18.2框架进行测试。
RtspClient可能会从ConnectAsync中抛出一个OperationCanceledException。所以,我试着测试这个场景。下面的测试抛出一个异常System.OperationCanceledException: The operation was canceled.,catch (OperationCanceledException)永远不会被执行。我在这里做错什么了?
RTSP
public interface IRtspClient : IDisposable
{
event EventHandler<RawFrame> FrameReceived;
Task ConnectAsync(CancellationToken token);
Task ReceiveAsync(CancellationToken token);
}使用的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;
}
}测试
[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按照@Dai的建议添加了缺失的await,但我的测试仍然失败。有人能看看测试代码吗?
发布于 2022-08-14 23:27:12
我发现了我的错误(除了@Dai注意到的以外)。我应该将测试中的await camera.ConnectAsync放在try-catch中,或者使用Assert.ThrowsExceptionAsync。我选择了后者。以下是工作测试:
[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);
}发布于 2022-08-14 22:17:44
您需要将返回的block.
try{}块内的delegate() try{})中的try{} Task保留在CancellationTokenSource is IDisposable中,因此您应该更改ConnectAsync_Canceled测试,将其封装在using()块中。H 216H 117也是如此,不要吞下异常--所以下面的代码捕获了两个异常,以便进行可能的调查,然后用throw; (don't use throw ex;: it resets the recorded stack-trace)重新抛出它们;相反,只需自己做throw; )。特别是带有request.和/或TaskCanceledException的
,需要将异常重新抛回原始调用方(即CancellationTokenSource的所有者);而如果在没有相应的Task“查看”的情况下捕获和处理TaskCanceledException,则调用方将假定操作成功,尽管取消了TaskCanceledException。将代码更改为:
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.
}
}https://stackoverflow.com/questions/73355352
复制相似问题