4

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

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

其中 PermanentCancellation 是 CancellationTokenSource 类型。

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

任何指针将不胜感激。

4

2 回答 2

2

因为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();
    }

}

并使用ICancellationTokenSourceas然后您可以在测试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在您的生产代码中使用。

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

于 2012-09-04T13:29:38.477 回答
2

我更进一步,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它是传入的,尽管该令牌中的内容不一定重要。

于 2022-01-18T15:49:09.093 回答