gpt4 book ai didi

c# - 验证模拟方法使用特定的 CancellationTokenSouce,该方法也被模拟

转载 作者:行者123 更新时间:2023-12-04 05:33:34 25 4
gpt4 key购买 nike

我试图验证特定的 CancellationTokenSource 是否用作方法调用中的实际参数。

        public void DataVerification(Object sender, EventArgs e)
{
_entity.PopulateEntityDataVerificationStage(_view.DataTypeInputs, _view.ColumnNameInputs, _view.InitialRow, _view.FinalRow, _view.CurrencyPair, _view.CsvFilePath, _view.ErrorLogFilePath);

//...

CancellationTokenSource tempCsvFileVerificationCancellation = new CancellationTokenSource();

_source.Source = tempCsvFileVerificationCancellation;

//Want to verify that TempCsvFileVerificationCancellation.Token is passed into the following method.
_verify.SetupCsvFileVerification(_entity, tempCsvFileVerificationCancellation.Token);

//...
}

以下是我的测试:
    [Test]
public void DataVerification_SetupCsvFileVerification_CorrectInputs()
{
Mock<IMainForm> view = new Mock<IMainForm>();

Mock<IUserInputEntity> entity = new Mock<IUserInputEntity>();

Mock<ICsvFileVerification> verify = new Mock<ICsvFileVerification>();
verify.Setup(x => x.SetupCsvFileVerification(It.IsAny<UserInputEntity>(), It.IsAny<CancellationToken>()));

CancellationTokenSource cts = new CancellationTokenSource();

Mock<ICancellationTokenSource> source = new Mock<ICancellationTokenSource>();
source.SetupSet(x => x.Source = It.IsAny<CancellationTokenSource>()).Callback<CancellationTokenSource>(value => cts = value);
source.SetupGet(x => x.Source).Returns(cts);
source.SetupGet(x => x.Token).Returns(cts.Token);

MainPresenter presenter = new MainPresenter(view.Object, entity.Object, verify.Object, source.Object);

presenter.DataVerification(new object(), new EventArgs());

verify.Verify(x => x.SetupCsvFileVerification(entity.Object, source.Object.Token));
}

错误信息如下:

对模拟的预期调用至少一次,但从未执行过:x => x.SetupCsvFileVerification(.entity.Object, (Object).source.Object.Token)
未配置任何设置。

source代表的类如下:
public interface ICancellationTokenSource
{
void Cancel();

CancellationTokenSource Source { get; set; }

CancellationToken Token { get; }
}

public class CancellationTokenSourceWrapper : ICancellationTokenSource
{
private CancellationTokenSource _source;

public CancellationTokenSourceWrapper(CancellationTokenSource source)
{
_source = source;
}

public CancellationTokenSource Source
{
get
{
return _source;
}
set
{
_source = value;
}
}


public CancellationToken Token
{
get
{
return Source.Token;
}
}

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

当我逐步完成单元测试时,cts 确实被分配了 TempCsvFileVerificationCancellation 的值。 source 中的 Token 属性,返回 Source.Token。我不知道我做错了什么。

任何指针/帮助将不胜感激。

谢谢

编辑

最佳答案

乍一看,它看起来应该可以工作,但实际上你可以尝试:

把verify上的匹配条件改成It.IsAny(),It.IsAny()看看到底有没有被调用。
- 如果没有,请通过代码调试并查看发生了什么
- 如果确实匹配,那么这是匹配的问题

尝试 entity.Object, It.IsAny() 来查看 UserInputEntity 是否错误。

如果 UserInputEntity 没问题,那么在源设置上放置一个回调。它不需要做任何事情,但允许您在调用 SetupCsvFileVerification 时检查正在使用的值。

更新
我想我找到了它,它与我的以下观点之一有关。您将 cts 初始化为一个值。它需要有一个初始值,因为设置

source.SetupGet(x => x.Source).Returns(cts); 
source.SetupGet(x => x.Token).Returns(cts.Token);

没有它会失败,因为它会立即评估 cts.Token 。这意味着这将返回测试中定义的 CancellationTokenSource 中的 token ,而不是生产代码中定义的 token (并使用回调存储)。

为确保您使用新的 cts 值,您应该将设置更改为
source.SetupGet(x => x.Source).Returns(() => cts);
source.SetupGet(x => x.Token).Returns(() => cts.Token);

这将推迟评估直到使用,即在集合的回调执行之后。

添加详细信息
问题是评估的时间

假设在测试设置中创建了一个 cts X,它有一个 token A。
然后,您将 Source 设置为返回 cts,并将 token 设置为返回 cts.Token
这些已评估 现在 ,gets 被告知返回 X 和 A。

运行时,cts 被使用回调的一组覆盖(将其称为 Y, token 为 B),它是验证使用的 B 值,因此失败。

通过将设置更改为使用 lambda,我们告诉他们使用“当你被调用时 cts 指向的任何值”,所以现在的序列是

设置 get - 不评估 CTS 或 token 值
通话验证
- 使用回调设置 cts
- 获取源 => 评估,使用新设置的值 (Y)
- 获取 token => 评估,使用新设置的值 (B)
验证 => 与 B 比较,通过

其他想法

CancellationTokenSource 的存在只是为了支持测试吗?

如果是这样,另一种方法是尝试将其替换为 ICancellationTokenProvider 这将取代新的 CancellationTokenSource();调用您的生产代码。这将允许您更轻松地将特定的 CancellationToken 注入(inject)代码中,从而验证 SetupCsvFileVerification()。

小问题-随意忽略

此外,除非您使用严格的行为,否则设置
verify.Setup(x => x.SetupCsvFileVerification(It.IsAny<UserInputEntity>(), 
It.IsAny<CancellationToken>()));

是多余的。它不返回任何内容,因此它不能用作 stub ,并且稍后您将显式验证调用。

同样,不需要将“cts”初始化为一个值,将其设置为 null 就足够了,因为设置源的回调应该填充它。

关于c# - 验证模拟方法使用特定的 CancellationTokenSouce,该方法也被模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12271734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com