简体   繁体   English

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

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

I have a conditional statement which should looks as follows:我有一个条件语句,应该如下所示:

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

where PermanentCancellation is of type CancellationTokenSource.其中 PermanentCancellation 是 CancellationTokenSource 类型。

Im wondering how i should set this up in my mock of _view.我想知道我应该如何在我的 _view 模拟中设置它。 All attempts thus far have failed :( and i cant find an example on google.到目前为止所有的尝试都失败了:(而且我在谷歌上找不到一个例子。

Any pointers would be appreciated.任何指针将不胜感激。

Because CancellationTokenSource.Cancel is not virtual you cannot mock it with moq. 因为CancellationTokenSource.Cancel不是虚拟的,所以你不能用moq来模拟它。

You have two options: 您有两种选择:

Create a wrapper interface: 创建一个包装器接口:

public interface ICancellationTokenSource
{
    void Cancel();
}

and an implementation which delegates to the wrapped CancellationTokenSource 以及委托给包装的CancellationTokenSource的实现

public class CancellationTokenSourceWrapper : ICancellationTokenSource
{
    private readonly CancellationTokenSource source;

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

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

}

And use the ICancellationTokenSource as PermanentCancellation then you can create an Mock<ICancellationTokenSource> in your tests: 并使用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());

And use the CancellationTokenSourceWrapper in your production code. 并在生产代码中使用CancellationTokenSourceWrapper

Or use a mocking framework which supports mocking non virtual members like: 或者使用支持模拟非虚拟成员的模拟框架,例如:

I went a step further and made a factory to create a CancellationTokenManager class that implements the interface.我更进一步,做了一个factory来创建一个实现接口的CancellationTokenManager类。 This was because my method has to take CancellationToken and I wanted granular control over .IsCancellationRequested() :这是因为我的方法必须采用CancellationToken并且我希望对.IsCancellationRequested()进行精细控制:

My CancellationTokenManagerFactory :我的CancellationTokenManagerFactory

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

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

and the manager:和经理:

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;
}

Then in a class utilizing:然后在课堂上使用:

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
    }
  }
}

Now if I check cancellation is requested more than once i can mock with different responses each time.现在,如果我多次检查取消请求,我可以每次都模拟不同的响应。 Additionally, any interfaces like IHostService can still be utilized because CancellationToken is passed in although it doesn't necessarily matter what is in that token.此外,仍然可以使用像IHostService这样的任何接口,因为CancellationToken已传入,尽管该令牌中的内容并不一定重要。

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

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