I mock a method from an interface which has optional parameters to return true.
However, depending on whether I pass all the optional parameters to the call or only the required parameters I get a different result.

以下是该行为的完整工作示例:

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

I would expect them to both return True as I set It.IsAny for all the parameters in the Setup.
What am I missing here?

我的Moq版本是4.20.70

推荐答案

的确,正如乔恩·斯基特所建议的那样,但由于我在通读问题时就已经有了这个 idea (所以在看到他的 comments 之前),而且我也不厌其烦地重现了这个问题,所以我冒昧地写下以下内容作为回答而不是 comments .

我不依赖于要判断的输出,而是将解决方案作为一个测试提供,它使用断言来演示修复是否有效:

[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>().正如乔恩所写的,它们不是同一类型的,这可能解释了为什么Setup不能捕获省略可选值的调用.

Csharp相关问答推荐

C#中的包版本控制

自定义JsonEditor,用于将SON序列化为抽象类

无法使用ternal- .net修复可空警告

Unity如何在PlayerPrefs中保存数据?

如何在NServicebus中配置学习传输的文件夹(NService bus 8)

解析需要HttpClient和字符串的服务

SignalR客户端不会打印队列位置'

System.Text.Json数据化的C#类映射

Nuget包Serilog.Sinks.AwsCloudwatch引发TypeLoadExceptions,因为父类型是密封的

Blazor EventCallback<;MyType<;T>;>;

用C#从Word文档中删除重复的节控件和文本内容控件

HttpClient 415不支持的媒体类型错误

CA1508:';NULL=>;TRUE;始终为';TRUE';.移除或重构条件(S)以避免死代码

当我没有此令牌时,为什么语法报告EOF错误?

MSTest--将消息直接写入StdOut和使用TestContext有什么不同?

WinUI 3中DoubleCollection崩溃应用程序类型的依赖属性

解决方案:延长ABP框架和ANGING OpenIddict中的令牌生命周期

WPF如何获取有关从一个视图模型更改另一个视图模型的信息

测试单个对象是否与Func<;T,bool>;匹配

C#LINQ多行条件