使用Moq设置并validation表达式

有没有办法设置和validation使用Moq表达式的方法调用?

第一次尝试是我想让它工作的那个,而第二次是让补丁部分工作的“补丁”(validation部分仍然失败)

 string goodUrl = "good-product-url"; [Setup] public void SetUp() { productsQuery.Setup(x => x.GetByFilter(m=>m.Url== goodUrl).Returns(new Product() { Title = "Good product", ... }); } [Test] public void MyTest() { var controller = GetController(); var result = ((ViewResult)controller.Detail(goodUrl)).Model as ProductViewModel; Assert.AreEqual("Good product", result.Title); productsQuery.Verify(x => x.GetByFilter(t => t.Url == goodUrl), Times.Once()); } 

Assert测试失败并抛出空引用exception,因为从不调用方法GetByFilter。

相反,我使用这个

 [Setup] public void SetUp() { productsQuery.Setup(x => x.GetByFilter(It.IsAny<Expression<Func>>())).Returns(new Product() { Title = "Good product", ... }); } 

测试通过Assert部分,但这次是validation失败,说它从未被调用过。

有没有办法用特定的表达式设置方法调用而不是使用genericsIt.IsAny()

更新

我在评论中也尝试了UfukHacıoğulları的建议并创建了以下内容

 Expression<Func> goodUrlExpression = x => x.UrlRewrite == "GoodUrl"; [Setup] public void SetUp() { productsQuery.Setup(x => x.GetByFilter(goodUrlExpression)).Returns(new Product() { Title = "Good product", ... }); } [Test] public void MyTest() { ... productsQuery.Verify(x => x.GetByFilter(goodUrlExpression), Times.Once()); } 

但是我得到了一个空引用exception,就像在第一次尝试中一样。

我的控制器中的代码如下

 public ActionResult Detail(string urlRewrite) { //Here, during tests, I get the null reference exception var entity = productQueries.GetByFilter(x => x.UrlRewrite == urlRewrite); var model = new ProductDetailViewModel() { UrlRewrite = entity.UrlRewrite, Culture = entity.Culture, Title = entity.Title }; return View(model); } 

以下代码演示了如何在此类方案中进行测试。 一般的想法是你对“真实”数据执行传入的查询。 这样,您甚至不需要“validation”,就好像查询不对,它将无法找到数据。

修改以满足您的需求:

 using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Moq; using NUnit.Framework; namespace StackOverflowExample.Moq { public class Product { public string UrlRewrite { get; set; } public string Title { get; set; } } public interface IProductQuery { Product GetByFilter(Expression> filter); } public class Controller { private readonly IProductQuery _queryProvider; public Controller(IProductQuery queryProvider) { _queryProvider = queryProvider; } public Product GetProductByUrl(string urlRewrite) { return _queryProvider.GetByFilter(x => x.UrlRewrite == urlRewrite); } } [TestFixture] public class ExpressionMatching { [Test] public void MatchTest() { //arrange const string GOODURL = "goodurl"; var goodProduct = new Product {UrlRewrite = GOODURL}; var products = new List { goodProduct }; var qp = new Mock(); qp.Setup(q => q.GetByFilter(It.IsAny>>())) .Returns>>(q => { var query = q.Compile(); return products.First(query); }); var testController = new Controller(qp.Object); //act var foundProduct = testController.GetProductByUrl(GOODURL); //assert Assert.AreSame(foundProduct, goodProduct); } } }