【发布时间】:2020-04-20 23:04:10
【问题描述】:
我有一个使用 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 在这里是正确的,但这意味着我不能在单元测试中等待它...
【问题讨论】:
标签: c# unit-testing moq