我开发了一个wpf-mvvm应用程序,该应用程序使用wmi将给定计算机中内置的内容记录到json文件中。我已经使用mvvm模型来开发应用程序,并且正在测试视图模型中的函数。因此,在编写测试以检查命令是否正确执行时,我遇到了一个令人困惑的错误。我试图验证,无论我在ICommand
的execute()
方法中抛出什么,模拟对话框和Mediator方法都会被命中。
让我困惑的是,当我调试测试时,它肯定会得到验证,并且我达到了我想要的所有方法,但当我只是运行测试时,有时(大约40%的运行(我会得到设置不匹配的异常。
确切的例外是:
Moq.MockException:MockIMediator:217:此模拟验证失败原因如下:
IMediator x => x.Send<bool>(It.IsAny<CreatePCCommand>(), It.IsAny<CancellationToken>())
:此设置不匹配。
我正在测试的代码如下:
private async Task CreateComputer(CancellationToken token)
{
var task = Task<Computer>.Factory.StartNew(() => _factory.FromWMI());
var (orderNumber, countryCode) = OpenDialog(); //Can be ignored since it's mocked to return default values.
Computer computer;
if (!string.IsNullOrWhiteSpace(orderNumber))
computer = await task.ConfigureAwait(false);
else
return;
if (await _mediatr.Send(new CreatePCCommand(orderNumber, countryCode, computer), token).ConfigureAwait(false))
{
var dialog = _ui.GetDialog("The PC was successfully documented.", "The PC was successfully documented.");
_ = dialog.ShowDialog();
}
else
{
var dialog = _ui.GetDialog("The documentation of the PC failed.", "The documentation of the PC failed.");
_ = dialog.ShowDialog();
}
}
测试用例是这样的:
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
[InlineData("Hello World")]
public void MainWindowViewModel_CreateComputerCommand_CallsTheSecondDialog(string input)
{
_mediatr.Setup(x => x.Send(It.IsAny<CreatePCCommand>(), It.IsAny<CancellationToken>())).ReturnsAsync(true).Verifiable();
_dialog.Setup(x => x.ShowDialog()).Returns(true).Verifiable();
var vm = new MainWindowViewModel(_mediatr.Object, _notifier.Object, _cache, _view.Object,
_computer.Object, _process.Object, _factory.Object);
vm.CreateComputerCommand.Execute(input);
Mock.Verify(_mediatr, _dialog);
}
到目前为止,我尝试的是将设置更改为以下任一项:
_mediatr.Setup(x => x.Send(It.IsAny<CreatePCCommand>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
_mediatr.Setup(x => x.Send(It.IsAny<CreatePCCommand>(), It.IsAny<CancellationToken>()).Result).Returns(true).Verifiable();
以上这些都没有解决问题,而且与上面显示的完整测试基本保持一致。尽管如此,当我调试时,我可以看到所有相关的行都被命中了,即使上面的其他设置也如我所料,但当在Visual Studio 2019的测试资源管理器中使用run all命令运行它时,它有时会失败。
对于版本控制,我使用Mediator版本8.0.0、Moq 4.16.1和Xuit 2.2.0。
有人见过这样的东西吗。我配置错误了吗?我的代码中有明显的错误吗?
当测试单独工作,但当您同时运行所有测试时却不工作时,这通常是它们共享某些状态(来自测试类成员、静态成员等(的迹象。
换句话说,Test1破坏了Test2的数据。
这个问题是在测试中避免设置和拆卸的原因之一。
我们可以看到你的测试中出现了哪些字段(如_mediatr
、_dialog
等(,所以这个假设似乎是合理的。
解决方案
您有时可以通过禁用测试并行化来解决这个问题。使用xUnit时,可以使用[assembly: CollectionBehavior(DisableTestParallelization = true)]
来执行此操作。您可以查看xUnit文档以了解更多详细信息。