我已经用同样的场景做了很多次了,但这一次失败了,我想不出原因,请帮帮我.

下面是我的代码,我已经try 了Moq和NSubsitute,但对于这两个,返回是null,但它应该返回json,我放在里面,我已经做了相同的在以前的项目,但从来没有遇到过这样的问题,我的头脑完全不工作.

public interface IMyInterface
{
    public string myOrder(List<Order> order);       
}

目标类

public class funcMyFunctionApp
{
    private readonly IMyInterface myInterface;
    private readonly TelemetryClient telemetryClient;
    private readonly ILogger _logger;

    public funcMyFunctionApp(IMyInterface _myInterface)
    {
        myInterface = _myInterface;
    }

    [FunctionName("func1")]
    public IActionResult func1([HttpTrigger(AuthorizationLevel.Function, "post",Route = "func1")] string jsoninput)
    {
        try
        {
            if (!string.IsNullOrEmpty(jsoninput))
            {
                return new OkObjectResult(myInterface.myOrder(JsonConvert.DeserializeObject<List<Order>>(jsoninput)));
            }
            else
            {
                return new BadRequestObjectResult("Bad Order");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
            if(ex.InnerException != null)
            {
                _logger.LogError(ex.InnerException.Message.ToString());
            }
            return new BadRequestObjectResult("Bad Order");
        }
    }
}

测试fixture

public void shouldReturnOkObjectResultifInputisValid()
{
    string ValidJson1 = @"[
        {
          ""CreatedBy"":""test@test.org"",
          ""OrderNo"":""Pizz111"",
          ""Amount"":""10$"",
        }
    ]";
    string ValidOutputJson1 = @"{
        ""OrderNo"": ""808098"",
        ""Item"": ""Pizza""
    }";
    Mock<IMyInterface> myInterfaceMock =new Mock<IMyInterface>();
    IMyInterface myInterfaceSubsititueMock = Substitute.For<IMyInterface>();
    var input = JsonConvert.DeserializeObject<List<Order>>(ValidJson1);
    myInterfaceMock.Setup(m=>m.myOrder(input)).Returns(ValidOutputJson1);
    
    //Local Arrange
    myInterfaceSubsititueMock.myOrder(ValidJson1).Returns(ValidOutputJson1);
    funcMyFunctionApp funcRequest = new funcMyFunctionApp(myInterfaceMock.Object);
    
    // Act
    var result = funcRequest.func1(ValidJson1);
    
    // Assert
    Assert.Multiple(() =>
    {
        Assert.That((((OkObjectResult)result).Value as string), Is.EqualTo(ValidOutputJson1));
    });
}  

我期望它应该返回Returns以下提供的字符串

推荐答案

TL;DR:JsonConvert.DeserializeObject<List<Order>>(jsoninput)不等同于JsonConvert.DeserializeObject<List<Order>>(ValidJson1).

对于MOQ,库使用object.Equals来确定形式参数和实际参数是否相同.换句话说,它执行引用类型的引用判断.这就是为什么即使您的两个JsonConvert.DeserializeObject方法调用返回相同的集合,但它们将是两个不同的List实例.

为了解决您的问题,在您的Setup呼叫中使用It.IsAny<List<Order>>():

myInterfaceMock
   .Setup(m=>m.myOrder(It.IsAny<List<Order>>()))
   .Returns(ValidOutputJson1);

DotNet小提琴:https://dotnetfiddle.net/dYcKk6


UPDATE #1

正如尼尔建议的那样,你可以进一步限制你的Setup英镑.It.IsAny并不关心形式和实际的参数相等.而不是只判断数据类型.

如果你想确保正式的和实际的集合参数是相同的,你可以使用It.Is:

// If ordering does not matter
.Setup(m=>m.myOrder(It.Is<List<Order>>(actual => input.All(actual.Contains))))
//OR
.Setup(m=>m.myOrder(It.Is<List<Order>>(actual => actual.All(input.Contains))))

// If ordering matters
.Setup(m=>m.myOrder(It.Is<List<Order>>(actual => input.SequenceEqual(actual))))
// OR
.Setup(m=>m.myOrder(It.Is<List<Order>>(actual => actual.SequenceEqual(input))))

要实现这一点,Order必须是record或实现IEquatable接口.

Csharp相关问答推荐

禁用AutoSuggestBox项目更改时的动画?

WPF Windows初始化正在锁定. Net 8中分离的线程

是否可以使用EF—Core进行临时部分更新?

不仅仅是一个简单的自定义按钮

在LINQ Where子句中使用新的DateTime

Blazor WebApp:原始异常:AADSTS700025:客户端是公共的,因此既不应显示客户端,也不应显示客户端

Amazon SP-API确认发货不设置&Quot;递送服务

使用预定义对象减少Task.Run/Factory.StartNew中的关闭开销

在.NET MAUI.NET 8中如何防止按钮点击时出现灰色反馈

UWP应用程序try 将打包的本机.exe文件加载为C#程序集

RX操作员使用先前值进行扫描,信号来自值本身

使用C#和.NET 7.0无法访问Cookie中的数据

正在从最小API-InvocationConext.Arguments中检索参数的FromBodyAttribute

ReadOnlyMemory访问基础索引的替代方案

如何使用.NET Aspire从Blazor应用程序与GRPC API通信?

用MongoDB c#驱动程序删除和返回嵌套数组中的文档

Visual Studio 17.8.0制表符自动完成问题--三缩进

如何解决System.StackOverflowException:抛出System.StackOverflowException类型的异常.&# 39;生成随机代码时发生异常?

项目参考和方法签名问题

更新实体框架上的被跟踪实体