moq icon indicating copy to clipboard operation
moq copied to clipboard

Adding Try Catch to Method returns empty List

Open Denisjc opened this issue 5 months ago • 1 comments

When I add a Try Catch block to my method that is calling the mocked object I get nothing in return

But removing the Try Catch block makes the mock return the correct List

` //Mock Setup

 var list = ClearanceDataHelpers.GetFullUnsuccessfulList();

  var unitOfWork = new Mock<IUnitOfWorkApp>();
  var repoMock = new Mock<IRepositoryViewAsync<ClearanceList>>();

  repoMock.Setup(r => r.GetListAsync(x => x.VisitorId == It.IsAny<int>())).ReturnsAsync(list);

  unitOfWork.Setup(x => x.ClearanceListRepo).Returns(repoMock.Object);
  return unitOfWork;

`

Unit Test Part var dataService = new DataService(_logger.Object, _cache.Object, unitOfWork.Object); var clearance = dataService.GetLatestClearanceByVisitorAsync(1, 1).Result;

Service Method GetLatestClearanceByVisitorAsync - Fails try { var list = await _unitOfWork.ClearanceListRepo.GetListAsync(x => x.VisitorId == visitorId); } catch (Exception ex) { }

Service Method GetLatestClearanceByVisitorAsync - Works with no Try Catch Block var list = await _unitOfWork.ClearanceListRepo.GetListAsync(x => x.VisitorId == visitorId);

Back this issue Back this issue

Denisjc avatar Aug 13 '25 16:08 Denisjc

I guess that your method GetListAsync() have the following signature :

Task<IList<T>> GetListAsync(Expression<Func<T, bool>> filter)

It is normal that it does not work (and return null) : You setup the GetListAsync() method and ask Moq to expected and instance of the Linq expression x => x.VisitorId == It.IsAny<int>(). In your GetListAsync() you pass an instance of an other expression.

In other words, imagine you have the following method which allows to get the instance of an expression :

private static Expression<Func<T, bool>> GetExpressionInstanceItSelf<T>(Expression<Func<T, bool>> expression)
{
    return expression;
}

And you execute the following code:

var instance1 = GetExpressionInstanceItSelf<ClearanceList>(x => x.VisitorId == It.IsAny<int>());
var instance2 = GetExpressionInstanceItSelf<ClearanceList>(x => x.VisitorId == visitorId);

Console.WriteLine(object.ReferenceEquals(instance1, instance2));

You will see that these two instances are differents, so for Moq the expression setup-ed and the expression pass-ed as argument when calling your GetListAsync() is different.

Normally to test your code you have to use the It.IsAny<T>() in the argument of the expected expression. The problem with It.IsAny<T>(), your setup will work with any expression.

repoMock.Setup(r => r.GetListAsync(It.IsAny<Expression<Func<ClearanceList, bool>>>()))
    .ReturnsAsync(list);

To check the expression, you can insert a Callback() method to check the parameter (expression) when your GetListAsync() method is called :

repoMock.Setup(r => r.GetListAsync(It.IsAny<Expression<Func<ClearanceList, bool>>>()))
    .Callback((Expression<Func<ClearanceList, bool>> filter) =>
    {
        var resultExpression = filter.Compile()(c);

        Assert.True(resultExpression);
    })
    .ReturnsAsync(list);

GillesTourreau avatar Sep 27 '25 18:09 GillesTourreau