2013-07-10 1 views
4

Moq에서 식을 사용하는 메서드 호출을 설정하고 확인하는 방법이 있습니까? 두 번째는 "패치"할 수는있을Moq를 사용하여 식 설정 및 확인

첫 번째 시도는, 내가 그것을 얻이하고 싶은 것입니다

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 부품 작품 테스트는 Assert에서 실패하고 null 참조 예외가 발생합니다. GetByFilter 메서드가 호출되지 않기 때문입니다.

대신하면 나는이

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

테스트가 어설 부분을 통과 사용하지만, 이번에는 그가 호출되지 않습니다 말하는 실패 확인입니다.

generic It.IsAny<>()을 사용하는 대신 특정 식으로 메서드 호출을 설정하는 방법이 있습니까?

업데이트

나는 코멘트에 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()); 
} 

을 생성하지만 첫 번째 시도에서와 같이 null 참조 예외를 얻을. 다음 코드는 시나리오에서 테스트하는 방법을 보여줍니다

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

을 따를

내 컨트롤러의 코드입니다. 일반적인 아이디어는 "실제"데이터에 대해 전달 된 쿼리를 실행하는 것입니다. 그렇게하면 쿼리가 올바르지 않은 것처럼 "Verify"가 필요하지 않습니다. 데이터를 찾지 못합니다.

수정은 사용자의 요구에 맞게 :

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

관련 문제