NSubstitute与Linq表达式不匹配 [英] NSubstitute not matching Linq Expression
问题描述
我正在实现存储库模式Query类,并使用NSubstitute进行测试.
I am implementing a repository pattern Query class and testing using NSubstitute.
存储库界面:
public interface IMyRepository
{
IQueryable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class;
}
DateTimeProvider接口:
DateTimeProvider interface:
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);
}
}
但是测试失败,并显示以下消息:
But the test fails with the following message:
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()
,这在应用程序和测试之间是不同的.
The DateTime and Status are being parsed into value()
which are different between the Application and the Test.
这是为什么?我该如何解决?
Why is this? How can I fix this?
推荐答案
For complicate expressions if often find it easier to assert on captured arguments by using callbacks than with Received()
. An (incomplete) example:
Expression<Func<Thing, bool>> receivedFilter receivedFilter = null;
myRepository.When(x => x.Query<Thing>(Arg.Any<...>))
.Do(x => receivedQuery = x.Arg<Expression<Func<Thing, bool>>>());
然后,对捕获的过滤器表达式进行断言.实际上,仅执行表达式的过滤器函数可能会更简单(请参见例如这里)
Then, assert on the captured filter expression. It might actually simpler to just execute the expression's filter func (see e.g. here)
Func<Thing, bool> predicate = receivedFilter.Compile();
var matchingThing = new Thing
{ CreatedDate = createdData, Status = Status };
// assert matching
predicate(matchingThing).Should().BeTrue();
// assert non.matching
predicate(nonMatchingThing).Should().BeFalse();
这种方法似乎会使测试变得更加黑框,但这通常不是一件坏事.
This approach seems to make the test a little more black-boxed but this is in general not a bad thing.
这篇关于NSubstitute与Linq表达式不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!