4

I want to mock this interface using Moq

IInterfaceToBeMocked {
IEnumerable<Dude> SearchDudeByFilter(Expression<Func<Dude,bool>> filter);
}

I was thinking of doing something like

_mock.Setup(method => method.SearchDudeByFilter( x=> x.DudeId.Equals(10) && X.Ride.Equals("Harley"))). Returns(_dudes);// _dudes is an in-memory list of dudes.

When I try to debug the unit test where i need this mocking, it says that "expression is not allowed" pointing towards the lambda. If it makes any difference I am using xUnit as the testing framework.

Colin Hebert
  • 91,525
  • 15
  • 160
  • 151
Perpetualcoder
  • 13,501
  • 9
  • 64
  • 99
  • 1
    I'll assume the missed closing parenthesis is a typo when copying to the site, and not answer because I wouldn't know what it could be if it compiles and fails during debug as you mention. – eglasius Sep 09 '10 at 17:48

1 Answers1

6

The following works fine for me with the Moq 4.0 Beta:

public class Dude 
{
    public int DudeId { get; set; }
    public string Ride { get; set; }
}

public interface IInterfaceToBeMocked 
{
    IEnumerable<Dude> SearchDudeByFilter(Expression<Func<Dude,bool>> filter);
}

and the unit test:

[TestMethod]
public void TestDudes()
{
    // arrange
    var expectedDudes = new[]
    {
        new Dude(), new Dude()
    };
    var mock = new Mock<IInterfaceToBeMocked>();
    mock.Setup(method => method.SearchDudeByFilter(
        x => x.DudeId.Equals(10) && x.Ride.Equals("Harley"))
    ).Returns(expectedDudes);

    // act
    // Remark: In a real unit test this call will be made implicitly
    // by the object under test that depends on the interface
    var actualDudes = mock.Object.SearchDudeByFilter(
        x => x.DudeId.Equals(10) && x.Ride.Equals("Harley")
    );

    // assert
    Assert.AreEqual(actualDudes, expectedDudes);
}

Now if you change something into the argument of actual method call the test will no longer pass because the mocked method will return the expected result only if the argument is the same:

var actualDudes = mock.Object.SearchDudeByFilter(
    x => x.DudeId.Equals(20) && x.Ride.Equals("Honda")
);

Remark: mocking methods that take lambda expressions is a new feature that was not available in previous versions where we need to use It.Is<SomeType> and It.IsAny<SomeType> parameter constraints.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • If one of the arguments is passed as a parameter e.g. `SearchDudeByFilter(int dudeId)` then the valid invocation is regarded as unverified because the expression tree doesn't quite match: `Expected invocation on the mock at least once, but was never performed: method => method.SearchDudeByFilter(x => x.DudeId.Equals(6) && x.Ride.Equals("Harley")) Performed invocations: IInterfaceToBeMocked.SearchDudeByFilter(x => (x.DudeId.Equals(value(MyFixture+<>c__DisplayClass33‌​).dudeId) AndAlso x.Ride.Equals("Harley")))` – Ashfaq Hussain Jan 09 '14 at 16:46