繁体   English   中英

检查是否使用 Moq 调用了 CancellationTokenSource.Cancel()

[英]Checking that CancellationTokenSource.Cancel() was invoked with Moq

我有一个条件语句,应该如下所示:

//...
if(_view.VerifyData != true)
{
    //...
}
else
{
    _view.PermanentCancellation.Cancel();
}

其中 PermanentCancellation 是 CancellationTokenSource 类型。

我想知道我应该如何在我的 _view 模拟中设置它。 到目前为止所有的尝试都失败了:(而且我在谷歌上找不到一个例子。

任何指针将不胜感激。

因为CancellationTokenSource.Cancel不是虚拟的,所以你不能用moq来模拟它。

您有两种选择:

创建一个包装器接口:

public interface ICancellationTokenSource
{
    void Cancel();
}

以及委托给包装的CancellationTokenSource的实现

public class CancellationTokenSourceWrapper : ICancellationTokenSource
{
    private readonly CancellationTokenSource source;

    public CancellationTokenSourceWrapper(CancellationTokenSource source)
    {
        this.source = source;
    }

    public void Cancel() 
    {
        source.Cancel();
    }

}

并使用ICancellationTokenSource作为PermanentCancellation然后您可以在测试中创建Mock<ICancellationTokenSource>

// arrange

var mockCancellationTokenSource = new Mock<ICancellationTokenSource>();
viewMock.SetupGet(m => m.PermanentCancellation)
        .Returns(mockCancellationTokenSource.Object)

// act

// do something

// assert

mockCancellationTokenSource.Verify(m => m.Cancel());

并在生产代码中使用CancellationTokenSourceWrapper

或者使用支持模拟非虚拟成员的模拟框架,例如:

我更进一步,做了一个factory来创建一个实现接口的CancellationTokenManager类。 这是因为我的方法必须采用CancellationToken并且我希望对.IsCancellationRequested()进行精细控制:

我的CancellationTokenManagerFactory

public interface ICancellationTokenManagerFactory
{
  ICancellationTokenManager CreateManager(CancellationToken token);
}

public class CancellationTokenManagerFactory : ICancellationTokenManagerFactory
{
  public ICancellationTokenManager CreateManager(CancellationToken token)
  {
    return new CancellationTokenManager(token);
  }
}

和经理:

public interface ICancellationTokenManager
{
  bool IsCancellationRequested { get; }

  CancellationToken CancellationToken { get; }
}

public class CancellationTokenManager : ICancellationTokenManager
{
  private readonly CancellationToken _token;

  public CancellationTokenManager(CancellationToken token)
  {
    _token = token;
  }

  public bool IsCancellationRequested
  {
    get
    {
      return _token.IsCancellationRequested;
    }
  }

  public CancellationToken CancellationToken => _token;
}

然后在课堂上使用:

public class MyService
{
  private readonly ICancellationTokenManagerFactory _factory = factory;
  public MyService(ICancellationTokenManagerFactory factory)
  {
    _factory = factory;
  }

  public void StartAsync(CancellationToken token)
  {
    manager = _factory.CreateManager(token);

    //check if cancelled
    if (!manager.IsCancellationRequested())
    }
      // do some work
    }
  }
}

现在,如果我多次检查取消请求,我可以每次都模拟不同的响应。 此外,仍然可以使用像IHostService这样的任何接口,因为CancellationToken已传入,尽管该令牌中的内容并不一定重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM