2013-07-10 2 views
4

Есть ли способ настроить и проверить вызов метода, который использует выражение с помощью Moq?Настройка и проверка выражения с помощью Moq

Первой попытка это один я хотел бы получить его на работу, в то время как второй один является «заплата», чтобы позволить Assert части работы (с проверкой части еще неисправным)

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 и выбрасывает исключение нулевой ссылки, потому что метод GetByFilter никогда не вызывается.

Если вместо этого я использую этот

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

Тест проходит часть Assert, но на этот раз это Убедитесь, что не в состоянии сказать, что он никогда не вызывается.

Есть ли способ настроить вызов метода с помощью определенного выражения вместо использования общего It.IsAny<>()?

Update

Я попробовал также предложение по Ufuk Hacıoğulları в комментариях и создал следующий

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

Но я получаю нулевой ссылочный исключение, как и в первой попытке.

код в мой контроллер как следовать

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); 
} 
+0

Вы можете назначить лямбда-выражение переменной и использовать его в настройках и проверка вызовов? –

+0

Не повезло. Обновите вопрос своим предложением – Iridio

+0

Возможно, я не понимаю, что вы пытаетесь сделать, но если вы просто пытаетесь проверить, что настройка была сопоставлена, разве вы не можете просто использовать VerifyAll? – DoctorMick

ответ

7

Следующий код демонстрирует, как проверить в таких сценариях. Общая идея заключается в том, что вы выполняете переданный запрос в отношении «реальных» данных. Таким образом, вам даже не нужно «Проверять», как будто запрос неверен, он не найдет данные.

Изменить в соответствии с вашими потребностями:

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); 
     } 
    } 
} 
+0

Хорошее решение Я не думал об этом подходе. Спасибо. – Iridio

Смежные вопросы