我模拟了一个接口中的方法,该方法具有可选参数来返回
true
。这是该行为的完整工作示例:
using Moq;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Abstractions;
namespace MoqTest
{
public interface IProcedureService
{
Task<bool> InterfaceMethod(string req1, int req2, int? opt1 = null, CancellationToken opt2 = default);
}
public class Tests
{
Mock<IProcedureService> _procedureService = new Mock<IProcedureService>();
ITestOutputHelper _output;
public Tests(ITestOutputHelper output) => _output = output;
[Xunit.Fact]
public async void DoTheTest()
{
_procedureService.Setup(x => x.InterfaceMethod(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
_output.WriteLine($"result from IsUniqueProcedureNameInWorkspace (using optional defaults) " +
$"{(await _procedureService.Object.InterfaceMethod("", 0))}"); // returns false
_output.WriteLine($"result from IsUniqueProcedureNameInWorkspace (NOT using optional defaults) " +
$"{(await _procedureService.Object.InterfaceMethod("", 0, 0, default))}"); // returns true
}
}
}
输出以下内容:
Standard Output:
result from IsUniqueProcedureNameInWorkspace (using optional defaults) False
result from IsUniqueProcedureNameInWorkspace (NOT using optional defaults) True
当我为设置中的所有参数设置
True
时,我希望它们都会返回 It.IsAny
。我的最小起订量版本是 4.20.70
确实正如乔恩·斯基特(Jon Skeet)已经建议的那样,但由于我在阅读问题时已经有了这个想法(所以在看到他的评论之前),而且由于我也不厌其烦地重现了这个问题,所以我冒昧地将以下内容写为答案而不是评论。
我不依赖于要检查的输出,而是提供解决方案作为测试,使用断言来证明修复有效:
[Fact]
public async Task FixWithAssertions()
{
_procedureService
.Setup(x => x.InterfaceMethod(
It.IsAny<string>(),
It.IsAny<int>(),
It.IsAny<int?>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result1 = await _procedureService.Object.InterfaceMethod("", 0);
var result2 = await _procedureService.Object.InterfaceMethod("", 0, 0, default);
Assert.True(result1);
Assert.True(result2);
}
我在
Setup
中唯一改变的就是我指出了 It.IsAny<int?>()
而不是 It.IsAny<int>()
。正如 Jon 所写,这些不是同一类型,这可以解释为什么 Setup
没有捕获省略可选值的调用。