- Moq

2011-07-11 12 views
13

Ben diğerleri arasında, aşağıdaki yöntem ile işler uygulama bir Birimi vardır:- Moq

T Single<T>(Expression<Func<T, bool>> expression) where T : class, new(); 

ve böyle Örneğin, diyoruz:

var person = _uow.Single<Person>(p => p.FirstName == "Sergi"); 

Single yönteminin FirstName == "Sergi" argümanı ile çağrıldığını nasıl doğrulayabilirim?

ben aşağıdakileri denedim ama boşuna: folowing hata

// direct approach 
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi")); 

// comparing expressions 
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi"); 

session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression)); 

Hepsi Sonuç: nasıl

Expected invocation on the mock at least once, but was never performed

herhangi bir fikir olduğu yapılabilir? Ben versiyonu Nuget dan 4.0.10827.0

UPDATE son Moq kullanıyorum:

Ne görüyorum olduğunu Belirli Bir örnek ben lambda, Verify eser içindeki dize hazır her kullandığınızda. Değişkenleri karşılaştırdığım anda başarısız olur. Tipik bir örnek:

// the verify 
someService.GetFromType(QuestionnaireType.Objective) 

session.Verify(x => x.Single<Questionnaire>(q => 
    q.Type == QuestionnaireType.Objective)); 


// QuestionnaireType.Objective is just a constant: 
const string Objective = "objective"; 


// the method where it's called (FAILS): 
public Questionnaire GetFromType(string type) 
{ 
    // this will fail the Verify 
    var questionnaire = _session 
     .Single<Questionnaire>(q => q.Type == type); 
} 

// the method where it's called (PASSES): 
public Questionnaire GetFromType(string type) 
{ 
    // this will pass the Verify 
    var questionnaire = _session 
     .Single<Questionnaire>(q => q.Type == QuestionnaireType.Objective); 
} 

Nasıl Verify gelip en kısa sürede lambda ifadede yöntem parametresini kullanın olarak başarısız?

Bu testi yazmak için uygun yol ne olurdu?

cevap

11

doğrudan yaklaşım benim için sadece iyi çalışır: Bu başarısız olur böylece

// direct approach 
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi")); 

ifade nesne eşdeğer ifadeler için gerçek dönmez: aşağıdaki çalıştırmak neden

// comparing expressions 
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi"); 

session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression)); 

anlamak NUnit testi: Test üstünde olduğunu gösterir olarak

[Test] 
public void OperatorEqualEqualVerification() 
{ 
    Expression<Func<Person, bool>> expr1 = p => p.FirstName == "Sergi"; 
    Expression<Func<Person, bool>> expr2 = p => p.FirstName == "Sergi"; 
    Assert.IsTrue(expr1.ToString() == expr2.ToString()); 
    Assert.IsFalse(expr1.Equals(expr2)); 
    Assert.IsFalse(expr1 == expr2); 
    Assert.IsFalse(expr1.Body == expr2.Body); 
    Assert.IsFalse(expr1.Body.Equals(expr2.Body)); 
} 

Ve

, eski tarafından karşılaştırarak pression vücut da başarısız olur, ancak dize karşılaştırma çalışır, bu nedenle bu kadar iyi çalışır:

// even their string representations! 
session.Verify(x => x 
    .Single(It.Is<Expression<Func<Person, bool>>>(e => 
     e.ToString() == expression.ToString())); 

Ve burada da çalışır cephanelik ekleyebilirsiniz testin bir daha stil:

[Test] 
public void CallbackVerification() 
{ 
    Expression<Func<Person, bool>> actualExpression = null; 
    var mockUow = new Mock<IUnitOfWork>(); 
    mockUow 
     .Setup(u => u.Single<Person>(It.IsAny<Expression<Func<Person, bool>>>())) 
     .Callback((Expression<Func<Person,bool>> x) => actualExpression = x); 
    var uow = mockUow.Object; 
    uow.Single<Person>(p => p.FirstName == "Sergi"); 

    Expression<Func<Person, bool>> expectedExpression = p => p.FirstName == "Sergi"; 

    Assert.AreEqual(expectedExpression.ToString(), actualExpression.ToString()); 
} 

size şöyle Başarısız olan birkaç test vakası var, muhtemelen farklı bir probleminiz var.

GÜNCELLEME:

string normal_type = "NORMAL"; 
// PersonConstants is a static class with NORMAL_TYPE defined as follows: 
// public const string NORMAL_TYPE = "NORMAL"; 
Expression<Func<Person, bool>> expr1 = p => p.Type == normal_type; 
Expression<Func<Person, bool>> expr2 = p => p.Type == PersonConstants.NORMAL_TYPE; 

Bir ifadesi içeren yöntemin bir örnek değişkeni başvuran: Güncellemenize üzerine, aşağıdaki kurulum ve ifadeleri düşünün. Diğer bir statik sınıfın bir const üyesine başvuran bir ifadeyi temsil eder. İki çalışma zamanında değişkenlere atanabilecek değerlerden bağımsız olarak farklı ifadelerdir.Bununla birlikte, string normal_type, const string normal_type olarak değiştirilirse, ifadeler, ifadenin sağ tarafındaki her bir referansla bir const aynıdır.

+0

Cevabınız için çok teşekkürler. Daha iyi bir kelime olmaması için yeni er ... bulgularına dayanarak sorumu güncelledim. Herhangi bir fikir? –

+0

Sorunu, sorunun ne olabileceğini ele almak için güncelledim. Bu gerçekten 'QuestionnaireType.Objective' türüne bağlıdır. ToString() 'i kullanırsanız, farklı türlerde olduklarını göreceksiniz. –

+0

Tekrar teşekkürler, sanırım mantıklı. Peki bu testi yazmanın en uygun yolu ne olurdu? Bu durumda, "doğrudan yaklaşım" için daha temiz bir kod yerine bir araç yerine alay etmenin ve engelin ... –

1

Ayrıca, parametre ifadesini beklenen ifadeyle karşılaştırmaya başka bir yaklaşımı paylaşmak isterim. Ben "nasıl ifadeleri karşılaştırmak" için StackOverflow arandı ve ben bu eşyalara önderlik etti: Sonra db4o.net için this Subversion repository neden oldu

. Projelerinden birinde Db4objects.Db4o.Linq.Expressions ad alanı, ExpressionEqualityComparer adında bir sınıf içerir. Bu projeyi depodan denetleyebildim, derledim, derleyin ve kendi projemde kullanmak için bir DLL yarattım. Sonuçta

session.Verify(x => x .Single(It.Is<Expression<Func<Person, bool>>>(e => new ExpressionEqualityComparer().Equals(e, expression))));, ExpressionEqualityComparer ve ToString() teknikleri hem ToString büyük olasılıkla olmak (Bu durumda return true: ExpressionEqualityComparer ile

, aşağıdaki gibi bir şey için Verify çağrıyı değiştirebilir daha hızlı - hız test edilmedi). Şahsen ben karşılaştırma yaklaşımını tercih ederim çünkü kendi kendini belgelemenin daha iyi olduğunu ve tasarım amacınızı daha iyi yansıttığını hissediyorum (ToString çıkışlarının bir dize karşılaştırması yerine ifade nesnelerini karşılaştırarak).

Not: Bu projede hala bir db4o.net lisans dosyası arıyorum, ancak yine de kodu değiştirmedim, telif hakkı bildirimini dahil ettim ve (sayfa herkese açık olduğundan) I Şimdilik bu kadarını kabul ediyorum ... ;-)