使用Moq对Expression <Func <T,bool >>参数进行模拟方法

Per*_*der 4 .net unit-testing moq mocking

我想用Moq模拟这个界面

IInterfaceToBeMocked {
IEnumerable<Dude> SearchDudeByFilter(Expression<Func<Dude,bool>> filter);
}
Run Code Online (Sandbox Code Playgroud)

我在考虑做类似的事情

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

当我尝试调试我需要这个模拟的单元测试时,它表示"不允许表达式"指向lambda.如果它有任何区别我使用xUnit作为测试框架.

Dar*_*rov 6

使用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);
}
Run Code Online (Sandbox Code Playgroud)

和单元测试:

[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);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您将某些内容更改为实际方法调用的参数,则测试将不再通过,因为只有在参数相同时,mocked方法才会返回预期结果:

var actualDudes = mock.Object.SearchDudeByFilter(
    x => x.DudeId.Equals(20) && x.Ride.Equals("Honda")
);
Run Code Online (Sandbox Code Playgroud)

备注:采用lambda表达式的模拟方法是我们需要使用It.Is<SomeType>It.IsAny<SomeType>参数约束的先前版本中不可用的新功能.