2

I am trying to mock a repository on which a lambda expression is executed. The method that I want to execute looks like this:

public SelectListItem GetProtocolById(int protocolId)
{
    var protocol = UnitOfWork.ProtocolRepository.FindAll(s => s.PROTOCOL_ID == protocolId).FirstOrDefault();
    return new SelectListItem()
    {
        Text = protocol.USER_DEFINED_ID,
        Value = protocolId.ToString()
    };
}

I created a mockRepository in another class

protected MockRepository mockRepository = new MockRepository(MockBehavior.Default);

I have an UnitOfWork and a protocols repositories and I mock them like this:

var protocolRepositoryMock = mockRepository.Create<IRepository<PROTOCOL>>();
var unitOfWorkRBMMock = mockRepository.Create<IUnitOfWorkRBM>();

The FindAll method from IRepository looks like this :

IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> where, params Expression<Func<TEntity, object>>[] includes);

And the definition of the IRepository in my IUnitOfWorkRBM is this one:

IRepository<PROTOCOL> ProtocolRepository { get; set; }

I have tried to mock the unitOfWorkMock for it to be able to execute the lambda expression like this:

 unitOfWorkRBMMock.Setup(s => s.ProtocolRepository.FindAll(It.IsAny<Expression<Func<PROTOCOL, bool>>>()))
                .Returns(new Func<Expression<Func<PROTOCOL, bool>>, IEnumerable<PROTOCOL>>(
                expr => protocolsList.Where(expr.Compile())));

But when I try to call the GetProtocolById method, the protocol comes null.

Any ideas on what I am doing wrong here ?

2 Answers 2

3

The value of the expression provided can be accessed in the Returns method. Use that to filter the fake list

Review following minimal example that was used to solve the problem.

[TestMethod]
public void _MyTestMethod() {
    //Arrange
    var expectedProtocolId = 1;
    var protocolsList = new List<PROTOCOL> {
        new PROTOCOL {
            PROTOCOL_ID = expectedProtocolId,
            USER_DEFINED_ID = "Some user defined Id"
        },
        new PROTOCOL {
            PROTOCOL_ID = 2,
            USER_DEFINED_ID = "Some other user defined Id"
        }
    };

    var unitOfWorkRBMMock = new Mock<IUnitOfWorkRBM>();

    unitOfWorkRBMMock
        .Setup(_ => _.ProtocolRepository.FindAll(It.IsAny<Expression<Func<PROTOCOL, bool>>>(), It.IsAny<Expression<Func<PROTOCOL, object>>[]>()))
        .Returns<Expression<Func<PROTOCOL, bool>>, Expression<Func<PROTOCOL, object>>[]>((expr, includes) => protocolsList.Where(expr.Compile()));

    var sut = new SUT(unitOfWorkRBMMock.Object);

    //Act
    var result = sut.GetProtocolById(expectedProtocolId);

    //Assert

    Assert.IsNotNull(result);
}


class SUT {
    private IUnitOfWorkRBM UnitOfWork;

    public SUT(IUnitOfWorkRBM unitOfWorkRBM) {
        this.UnitOfWork = unitOfWorkRBM;
    }

    public SelectListItem GetProtocolById(int protocolId) {
        var protocol = UnitOfWork.ProtocolRepository.FindAll(s => s.PROTOCOL_ID == protocolId).FirstOrDefault();
        return new SelectListItem() {
            Text = protocol.USER_DEFINED_ID,
            Value = protocolId.ToString()
        };
    }
}

public interface IUnitOfWorkRBM {
    IRepository<PROTOCOL> ProtocolRepository { get; set; }
}

public interface IRepository<TEntity> {
    IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> where, params Expression<Func<TEntity, object>>[] includes);
}

public class PROTOCOL {
    public int PROTOCOL_ID { get; set; }
    public string USER_DEFINED_ID { get; set; }
}
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you but when I do it like this, when I call the GetProcolById method it gives me an Exception of type "System.Reflection.TargetParameterCountException" with the error message "Parameter count mismatch". Do you have any idea why is this happening ? Thanks again !!!
@Sebastian, Can you narrow does exactly where that error is thrown. a method that is expecting x number of parameters if getting y number of parameters. Does FindAll have any optional parameters?
the error is thrown when the line "var protocol = UnitOfWork.ProtocolRepository.FindAll(s => s.PROTOCOL_ID == protocolId).FirstOrDefault();" is executed. I have tried taking out the lambda expression from it and replacing it with null, same result.
@Sebastian, Ok update question with definition of unit of work and repository. I should be able to replicate your problem with that and try to properly setup the mock with that information.
I have added the only line that was missing from the code, the one with the definition of the mockRepository. There is also that piece of code for the definition of the list that you gave me. Everything else is the same.
|
0

you don't need to compile - you can Return expected result directly.

  unitOfWorkRBMMock.Setup(s => s.ProtocolRepository.FindAll(It.IsAny<Expression<Func<PROTOCOL, bool>>>()))
                    .Returns(new List<PROTOCOL>());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.