首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟单元测试失败的OperationCanceledException场景

模拟单元测试失败的OperationCanceledException场景
EN

Stack Overflow用户
提问于 2022-08-14 21:55:17
回答 2查看 80关注 0票数 0

我使用Moq4.18.2框架进行测试。

RtspClient可能会从ConnectAsync中抛出一个OperationCanceledException。所以,我试着测试这个场景。下面的测试抛出一个异常System.OperationCanceledException: The operation was canceled.catch (OperationCanceledException)永远不会被执行。我在这里做错什么了?

RTSP

代码语言:javascript
复制
public interface IRtspClient : IDisposable
{
    event EventHandler<RawFrame> FrameReceived;

    Task ConnectAsync(CancellationToken token);
    Task ReceiveAsync(CancellationToken token);
}

使用的IRtspClient方法

代码语言:javascript
复制
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;
    }
}

测试

代码语言:javascript
复制
[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,但我的测试仍然失败。有人能看看测试代码吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-14 23:27:12

我发现了我的错误(除了@Dai注意到的以外)。我应该将测试中的await camera.ConnectAsync放在try-catch中,或者使用Assert.ThrowsExceptionAsync。我选择了后者。以下是工作测试:

代码语言:javascript
复制
[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);
}
票数 0
EN

Stack Overflow用户

发布于 2022-08-14 22:17:44

您需要将返回的block.

  • Exceptions保存在try{}块内的
  • --否则同步控制将立即将抛入匿名函数(或本地函数或lambda方法,或you 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。

将代码更改为:

代码语言:javascript
复制
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.
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73355352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档