c# - 最小起订量在列出呼叫时说 0 个呼叫?
问题描述
我有一个使用 Moq 模拟接口和验证调用的单元测试。这是测试代码:
[Fact]
public void NewBlank_InvokesManagerAdd()
{
// ReSharper disable once AssignNullToNotNullAttribute
var newPath = Path.Combine(_testSaveDirectory, "InvokeBlank.txt");
_dbManagerMock.Setup(manager => manager.KeynoteDBs).Returns(new ObservableCollection<KeynoteDBVM>());
_dialogMock.Setup(dialog => dialog.GetSaveFileDialogResult(It.IsAny<SaveFileDialogData>()))
.Returns(newPath);
_commands.CmdNewBlank.Execute(null);
_dbManagerMock
.Verify(manager => manager.AddDB(It.IsAny<KeynoteDB>(), It.IsAny<int>()),
Times.Once);
}
但是,当我运行它时,我得到了这个测试失败:
Moq.MockException
Expected invocation on the mock once, but was 0 times: manager => manager.AddDB(It.IsAny<KeynoteDB>(), It.IsAny<int>())
Performed invocations:
Mock<IDBManager:1> (manager):
IDBManager.KeynoteDBs
IDBManager.IsLoading = True
IDBManager.ActiveDB
IDBManager.AddDB(KeynoteDB, -1)
IDBManager.ActiveDB
IDBManager.IsLoading = False
at Moq.Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)
at Moq.Mock`1.Verify[TResult](Expression`1 expression, Func`1 times)
at KMCore_Tests.AppCommandsTests.NewBlank_InvokesManagerAdd() in *my path*\AppCommandsTests.cs:line 140
它不是在中间的调用列表中列出该调用 1 次吗?怎么说它有 0 次调用?我错过了什么?我觉得我一定错过了一些愚蠢的东西,但我看不到它......
编辑
好的,结果证明这是一个竞争条件问题,因为命令是异步的。命令执行调用了一个 async void 方法,并且它必须在实际调用之前就已经达到了断言(或者至少这是我能想到的全部)。我在调用执行之后和断言之前放入了一个 await Task.Delay(500) ,它现在正在通过。
有没有更好的方法来测试这种情况?这些命令本质上是按钮处理程序,因此根据我的理解,我认为 async void 在这里是正确的,但这意味着我不能在单元测试中等待它...
解决方案
你应该避免使用 async void。
async void
意味着火和忘记。在您的情况下,您似乎不希望这样做,因为您需要等到异步方法完成。
如果您无法更改方法签名,则可以将async void
方法体移动到Task
返回方法。
例如,改变
public async void MyAsyncVoidMethod()
{
await Task.Delay(500);
MethodToBeCalled();
}
至
// Wait this task in unit test
public Task MyAsyncTask { get; private set; }
public async void MyAsyncVoidMethod()
{
MyAsyncTask = MyAsyncTaskMethod();
await MyAsyncTask;
}
public async Task MyAsyncTaskMethod()
{
await Task.Delay(500);
MethodToBeCalled();
}
或者,如果在命令完成后触发了任何事件,您还可以挂钩其中一个事件以在您的测试中保持通知。
推荐阅读
- php - 回退后 WebView 引用 (HTTP_REFERER) 标头不起作用
- amazon-web-services - 如何并行运行 AWS GLUE 作业?
- python - 为什么我在这个列表理解问题中得到 UnboundLocalError?
- wix - 在捆绑链执行结束时运行 PowerShell 脚本
- service - symfony 5 服务问题 => 不在对象上下文中使用 $this
- python - Python - 国旗和肤色表情符号无法正确显示
- android - 无法在颤振中创建应用程序目录
- java - 使用 Java 使用 selenium 在电子应用程序上切换句柄
- magento2 - Magento 2.4.1 将 vat_id 添加到新订单确认模板
- react-native - 如何在 react-native 中映射来自 redux 的数据