NSubstitute不匹配Linq Expression

时间:2014-10-20 13:44:59

标签: linq repository-pattern linq-expressions nsubstitute

我正在实现一个存储库模式Query类并使用NSubstitute进行测试。

存储库界面:

public interface IMyRepository
{
    IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class;
}

DateTimeProvider界面:

public interface IMyDateTimeProvider
{
    DateTime GetDateNow();
}

应用程序界面:

public interface IMyApplication
{
    List<Thing> GetThingsByQuery(int status);
}

应用程序实施:

public class MyApplication : IMyApplication
{
    private readonly IMyRepository myRepository;

    private readonly IMyDateTimeProvider myDateTimeProvider;

    public MyApplication(IMyRepository myRepository, IMyDateTimeProvider myDateTimeProvider)
    {
        this.myRepository = myRepository;
        this.myDateTimeProvider = myDateTimeProvider;
    }

    public List<Thing> GetThingsByQuery(int status)
    {
        var createdDate = this.myDateTimeProvider.GetDateNow();

        return this.myRepository.Query<Thing>(t => t.CreatedDate == createdDate && t.Status == status).ToList();
    }
}

测试:

[TestClass]
public class ApplicationTest
{
    private IMyApplication myApplication;

    private IMyDateTimeProvider myDateTimeProvider;

    private IMyRepository myRepository;

    [TestMethod]
    public void QueriesRepository()
    {
        // Arrange
        var createdDate = new DateTime(2014, 1, 1);

        this.myDateTimeProvider.GetDateNow().Returns(createdDate);

        const int Status = 1;

        // Act
        this.myApplication.GetThingsByQuery(Status);

        // Assert
        this.myRepository.Received().Query<Thing>(t => t.CreatedDate == createdDate && t.Status == Status);
    }

    [TestInitialize]
    public void TestInitialize()
    {
        this.myRepository = Substitute.For<IMyRepository>();

        this.myDateTimeProvider = Substitute.For<IMyDateTimeProvider>();

        this.myApplication = new MyApplication(this.myRepository, this.myDateTimeProvider);
    }
}

但测试失败并显示以下消息:

NSubstitute.Exceptions.ReceivedCallsException: Expected to receive a call matching:
    Query<Thing>(t => ((t.CreatedDate == value(MySolution.Test.ApplicationTest+<>c__DisplayClass0).createdDate) AndAlso (t.Status == 1)))
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
    Query<Thing>(*t => ((t.CreatedDate == value(MySolution.Application.MyApplication+<>c__DisplayClass0).createdDate) AndAlso (t.Status == value(MySolution.Application.MyApplication+<>c__DisplayClass0).status))*)

DateTime和Status被解析为value(),它们在应用程序和测试之间是不同的。

这是为什么?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

正在使用Expression的默认相等比较器(引用相等):

例如,(t => t.CreatedDate == createdDate && t.Status == Status``)中的表达式:

this.myRepository.Received().Query<Thing>(t => t.CreatedDate == createdDate  
                                            && t.Status == Status          );

是表达式的不同实例:

return this.myRepository.Query<Thing>(t => t.CreatedDate == createdDate  
                                        && t.Status == status          ).ToList();

要修复验证此方法,请查看argument matchers within NSubstitute

但作为一个例子:

Func<Expression<Thing, bool>, bool> validator = 
    // TODO this needs to be written properly, based on the expression, 
    // not its string representation
    e => e.Body.ToString() == "t.CreatedDate == createdDate  
      && t.Status == Status"; 
this.myRepository.Received().Query<Thing>(Arg.Is<Expression<Thing, bool>>(validator));