我正在模拟我的存储库界面,我不知道如何设置一个接受表达式并返回一个对象的方法?我正在使用Moq和NUnit
接口:
public interface IReadOnlyRepository : IDisposable
{
IQueryable<T> All<T>() where T : class;
T Single<T>(Expression<Func<T, bool>> expression) where T : class;
}
使用IQueryable进行测试已设置,但不知道如何设置T Single:
private Moq.Mock<IReadOnlyRepository> _mockRepos;
private AdminController _controller;
[SetUp]
public void SetUp()
{
var allPages = new List<Page>();
for (var i = 0; i < 10; i++)
{
allPages.Add(new Page { Id = i, Title = "Page Title " + i, Slug = "Page-Title-" + i, Content = "Page " + i + " on page content." });
}
_mockRepos = new Moq.Mock<IReadOnlyRepository>();
_mockRepos.Setup(x => x.All<Page>()).Returns(allPages.AsQueryable());
//Not sure what to do here???
_mockRepos.Setup(x => x.Single<Page>()
//----
_controller = new AdminController(_mockRepos.Object);
}
答案 0 :(得分:40)
您可以这样设置:
_mockRepos.Setup(x => x.Single<Page>(It.IsAny<Expression<Func<Page, bool>>>()))//.Returns etc...;
但是你遇到了Moq的一个缺点。你可能希望在那里放置一个实际的表达式,而不是使用It.IsAny
,但是Moq不支持设置带有特定表达式的表达式的方法(这是一个很难实现的特性)。难点在于必须弄清楚两个表达式是否相同。
因此,在您的测试中,您可以传入任何 Expression<Func<Page,bool>>
,它会传回您设置模拟的任何内容。测试的价值有点稀释。
答案 1 :(得分:7)
让.Returns调用对你的allPages变量返回表达式的结果。
_mockRepos.Setup(x => x.Single<Page>(It.IsAny<Expression<Func<Page, bool>>>()))
.Returns( (Expression<Func<Page, bool>> predicate) => allPages.Where(predicate) );
答案 2 :(得分:4)
我发现应使用It.Is<T>
代替It.IsAny<T>
以获得更准确的结果。
Page expectedPage = new Page {Id = 12, Title = "Some Title"};
_mockRepos.Setup(x => x.Single<Page>(It.Is<Expression<Func<Page, bool>>>(u => u.Compile().Invoke(expectedPage))))
.Returns(() => expectedPage);
答案 3 :(得分:1)
在没有It.IsAny<>
的情况下使用Moq&#39; .CallBack
会强制您编写测试未涵盖的代码。相反,它允许任何查询/表达式通过,从单元测试的角度来看,使得模拟基本没用。
解决方案:你需要使用Callback来测试表达式,或者你需要更好地约束你的模拟。无论哪种方式都是混乱和困难的。只要我一直在练习TDD,我就已经处理过这个问题了。我终于把一个帮助类放在一起,使它更具表现力和更少杂乱。以下是一个可能的最终结果的示例:
mockPeopleRepository
.Setup(x => x.Find(ThatHas.AnExpressionFor<Person>()
.ThatMatches(correctPerson)
.And().ThatDoesNotMatch(deletedPerson)
.Build()))
.Returns(_expectedListOfPeople);
以下是关于它的博客文章,并提供源代码:http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/