Customizing and validating expressions with Moq

Is there a way to set up and test a call to a method that uses an expression using Moq?

The first attempt is that I would like to make it work, and the second is a “patch” so that the Assert part works (while the verification part still did not work)

 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()); } 

The test test fails with an Assert error and throws a null reference exception because the GetByFilter method is never called.

If instead I use this

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

The test passes part of Assert, but this time Verify, which does not say that it is never called.

Is there a way to customize a method call with a specific expression instead of using the generic It.IsAny<>() ?

Update

I also tried Ufuk Hacıoğulları's suggestion in the comments and created the following

 Expression<Func<Product, bool>> 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()); } 

But I get a null reference exception, as in the first attempt.

The code in my controller is as follows

 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); } 
+4
c # moq
source share
1 answer

The following code demonstrates how to test in such scenarios. The general idea is that you are fulfilling a submitted query regarding "real" data. Thus, you don’t even need to “Check”, as if the request was incorrect, it will not find the data.

Change according to your needs:

 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<Func<Product, bool>> 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<Product> { goodProduct }; var qp = new Mock<IProductQuery>(); qp.Setup(q => q.GetByFilter(It.IsAny<Expression<Func<Product, bool>>>())) .Returns<Expression<Func<Product, bool>>>(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); } } } 
+7
source share

All Articles