2011-09-19 20 views
7

arabiriminde bildirilen olay yükseltmek Olay soyut sınıf alay olay yükseltmek için çalışırken birim testi ve alma istisna alıyorum. İşte örnek kod:C# ve Moq, soyut sınıf mock

public abstract class AbstractBase : EntityObject 
    {} 

    [TestMethod] 
    public void MyTest() 
    { 

     var mock = new Mock<AbstractBase>(); 
     var notificationMock = entityMock.As<INotifyPropertyChanged>(); 

     var propertyChangedMapper = new PropertyChangedMapper(); 

     bool eventReceived = false; 
     propertyChangedMapper.MyPropertyChanged += 
      (sender, eventArgs) => 
       { 
        eventReceived = true; 
       }; 

     propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object); 

     Assert.IsFalse(eventReceived); 

     notificationMock.Raise(e=>e.PropertyChanged += null, 
            new PropertyChangedEventArgs("Property1")); 

     Assert.IsTrue(eventReceived); 
    } 

Açıkçası ben INotifyPropertyChanged üzerinde alay kullanabilir ve olay gayet yükseldi, ancak Mock<INotifyPropertyChanged>

EDIT kullanılıyorsa PropertyChangedMapper iç ben başarısız AbstractBase gönderenin döküm gerekir: Mock.As<>() kullanarak öneriye gitmek için doğru yol gibi görünüyor, yukarıdaki tek sorun, olay notificationMock yükseldi nesnenin orijinal alay ile ilgisi yok olmasıdır. Kod:

 notificationMock.Object.PropertyChanged += (s, e) => 
     { 
      var result = "this one is fired as it should"; 
     }; 

     mock.Object.PropertyChanged += (s, e) => 
     { 
      var result = "this one is not called but is actually what I need"; 
     }; 

     notificationMock.Raise(e => e.PropertyChanged += null, 
       new PropertyChangedEventArgs("Property1")); 
+0

O sürece kimse denilen olsun sürece, çağıran hangisinin önemi yoktur. Benim tahminim aslında birini ya da diğerini kurabiliyor olman. Ancak, her ikisini de kurmak, bir diğerinin üzerinde seçen taklitlere yol açacaktır. –

+0

Hangi çağrının önemli olmadığı konusunda daha fazla kanıt için, tip sisteminin sanal üyeler ve geçersiz kılmaları için benzer şekilde çalıştığını düşünün. Örneğin, AbstractBase'e EntityObject öğesinin INPC olayı için bir geçersiz kılma eklediyseniz, EntityObject'in sürümünü çağırmak için herhangi bir kod kullanan herhangi bir kodun soyut yolu yoktur. EntityObject'e atsanız bile, AbstractBase üyesi çağrılır. Bir baz üye geçersiz kılındığında, sadece türeyen sınıf orjinal taban elemanına erişebilir. –

cevap

1

İstediğiniz cast yapmak mümkün olabilir. Moq alayları, genel argüman aracılığıyla bireysel bir türe bağlandığından, apaçıkça ek arayüzleri veya süper sınıfları açıkça aşamalı olarak eklemeniz ve ardından son ürünü testinizde kullanmanız gerekir. Bunun nasıl yapılacağının hızlı bir örneği aşağıdadır.

var baseMock = new Mock<AbstractBase>(); 
var inpcMock = baseMock.As<INotifyPropertyChanged>(); 

// ...setup event... 

propertyChangedMapper.Subscribe(inpcMock.Object); 

// ... assertions ... 
+1

Harika bir özellik! Ancak olayın inpcMock.Raise (e => e.PropertyChanged + = null, yeni PropertyChangedEventArgs ("Property1")) - 'herhangi bir fikir neden? – Paul

+0

Lütfen yukarıdaki güncellemeye bakın – Paul

1

Bunu yaptığınız şekilde verildiğinde, olayın hiçbir uygulaması yoktur. Arayüzün kendisi sadece "PropertyChanged olayım var" yazan sözleşmedir. Bu etkinliği yükseltmek istiyorsanız, hiçbir şey yapmasa bile bir işleyici sağlamanız gerekir. Etkinliği yükseltmek için sahte sınıftaki PropertyChanged olayını uygulayın.

GÜNCELLEME:

sizin AbstractBase için bu kodu deneyin: Bir virtual olay olarak ilan sizin PropertyChanged olay

public abstract class AbstractBase : INotifyPropertyChanged 
{ 
    public virtual event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 
+0

Bu istisnayı çözmek için tam olarak ne yapılmalı? – Paul

+1

"Genel soyut sınıf ÖzetBase: INotifyPropertyChanged {}" gibi kodlar derlenemiyor, buradaki kodu kısalttığını düşünüyorum ... – David

+0

@Paul: Güncellemeye bakın. –

1

mi?

public abstract class AbstractBase : INotifyPropertyChanged 
{ 
    public virtual event PropertyChangedEventHandler PropertyChanged; 
} 

(Ayrıca bakınız:. Jon Skeet on virtual events) Eğer sahte bir mult-mock yaparsanız

+0

numaralı düzenlemeye bakınız. Yukarıdaki – Paul

+0

numaralı düzenlemeye bakınız. Orijinal kodunuz benim için gayet iyi çalışıyordu ("As <>()" maddesinin tamamı hariç). – ladenedge

+0

Olayı sanal hale getirmek de, ancak bu yalnızca olayları uygulayan sınıfımsa. Zaten bir uygulamaya sahip olan temel sınıflardan miras alırken - olayları sanallaştırmanın bir yolu yoktur. Cevabınız için teşekkürler. – Paul