I have done this many times with the same, scenario but this time it is failing and I am not able to figure out the reason, please help me out.
Below is my code, I have tried with both Moq, and NSubsitute, but for both, returns is returning null but it should return the json, I am putting inside, I have done the same in previous projects as well, but never faced such an issue, my mind totally not working.
public interface IMyInterface
{
public string myOrder(List<Order> order);
}
Target Class
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");
}
}
}
Test Fixture
public void shouldReturnOkObjectResultifInputisValid()
{
string ValidJson1 = @"[
{
""CreatedBy"":""[email protected]"",
""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));
});
}
I am expecting that it should return the string provided under Returns
TL;DR:
JsonConvert.DeserializeObject<List<Order>>(jsoninput)is not the same asJsonConvert.DeserializeObject<List<Order>>(ValidJson1).In case of Moq, the library uses
object.Equalsto determine whether the formal and actual parameters are the same. In other words it performs reference check for reference types. That's why even though your twoJsonConvert.DeserializeObjectmethod calls return the same collection, but they will be two different List instances.In order to solve your problem use
It.IsAny<List<Order>>()in yourSetupcall:Dotnet fiddle: https://dotnetfiddle.net/dYcKk6
UPDATE #1
As it was suggested by Neil you can further restrict your
Setup. TheIt.IsAnydoes not care about formal and actual parameters equality. Rather than it checks only data type.If you want to make sure that the formal and actual collection parameters are the same you can utilize
It.Is:To make this work
Ordermust be either arecordor implement theIEquatableinterface.