2010-09-24 27 views
5

Aşağıdaki metod imzam var:NSubstitute ref parametrelerini destekliyor mu?

void SetItem(ref AddressItem item); 

Bunun gibi bir parametre kısıtlaması yapıyorum:

IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
AddressItem item = null; 
form.SetItem(Arg.Is(item)); 

Ancak bu hata nedeniyle başarısız oluyor. Ref dışarı çıkarsa o zaman iyi çalışır. Ama burada referans olarak geçmem gerekiyor.

Herhangi bir fikir nasıl elde edilir?

Yan Not: Nihai hedefim, eğer boş değerin boş olması durumunda SetItem'e bir istisna atmaktır. Bununla ilgili yardımcı olabilirseniz, ekstra puan alırsınız!

+0

Neden burada "ref" kullanmanız gerektiğini merak ediyorum. Açıklayabilir misin? –

+0

Eh, IT departmanımı NSubstitute ve Moles kullanarak ünite testinde eğitmek için örnek bir proje hazırlıyorum. Bunun bir parçası olarak Linq-To-SQL'i köstebek yapmak istiyorum. Bunu yapmak için, bir Linq'den sql sorgusuna döndürülen bir nesneye bazı güncelleştirmeler yapmam gerekiyordu. Nesneyi "ref" ile iletmemiş olsaydım, güncelleştirme başarısız oldu (çünkü artık sorgulanan nesne sorgulanmıyordu.) Bu, linq için sql için "en iyi uygulama" olmayabilir, ancak ben eğitim birimi testi, Linq değil. – Vaccano

+0

Kodumdaki soruyu/cevabı aşağıdaki gibi görüyorsunuz: http://stackoverflow.com/questions/3766417/save-changes-in-linq-to-sql/3770482#3770482 – Vaccano

cevap

10

NSubstitute, arg eşleştirme ref parametreleri için doğrudan desteğe sahip değildir, ancak genelde onlarla birlikte çalışır.

Sorunuzda belirtildiği gibi ref'u kullanmak zorunda olduğunuzu kabul edeceğim, ancak ref'dan kaçınmanız halinde API'nizin testi daha kolay olacaktır (kullandığınız çerçevelerden bağımsız olarak). Eğer yerine içine çok fazla davranışı itmeye çalışan olmadığından emin olun, sizin yan not için

form.SetItem(ref item); 

:

sizin acil soruya yanıt olarak

, Size ikinci kod örneğini güncelleyerek bir ref geçebilir . Bunu yaptığım zaman, test ettiğim sınıf ve bağımlılıkları arasındaki iletişimi basitleştirmem gereken bir işaret olduğunu anladım. (Ya da sahte bir nesnede gerçekten çok fazla mantığa ihtiyacım varsa, kodu üretmek yerine bir kod koyacağım; genellikle daha basit olabilir.)

Bu çağrı için bir istisna atmanın birkaç yolu vardır. :

form.When(x => x.SetItem(ref item)).Do(x => { throw new ArgumentNullException(); }); 

Bu boş ref seslenen tek bir özel durum oluşturur. Bu davranışı seçmiş olduğunuz argümana bağlı olarak seçmeli olarak da ekleyebilirsiniz, bunun yerine muhtemelen tavsiyede bulunmanızı tavsiye ederim. Sadece IAddAddressForm arg boş durum atar ne zaman test ediyoruz sınıf düzgün tepki verdiğini kontrol etmek istiyorsanız

form.WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { 
     if (x[0] == null) 
      throw new ArgumentNullException(); 
    }); 

Son olarak, muhtemelen sadece bu yapardım:

form 
    .WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { throw new ArgumentNullException(); }); 

Bu şekilde size don Tartışmanın ne olduğu gerçekten umrumda değil, sadece test ettiğiniz kodun bu duruma uygun şekilde tepki verdiğinden emin olmak istersiniz.

Bu yardımcı olur umarım.

YAN NOT:

Eğer çağrı kendisi dışında tanımlamak gerekir bir out veya ref argüman boyunca arg eşleyici (gibi Arg.Any<AddressItem>()) kullanmak istiyorsanız (bu eğilimli biraz hata olabilir : Eşleştiricileri, aramaya girecekleri sırayla aynı sırada tanımladığınızdan emin olmanız gerekir:

 IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
     AddressItem item = Arg.Is<AddressItem>(y => y.Number == 14); 
     form 
      .When(x => x.SetItem(ref item)) 
      .Do(x => { throw new ArgumentNullException(); }); 
     var address = new AddressItem { Number = 14 }; 
     form.SetItem(ref address); 
+0

Çok eksiksiz cevap! Çok teşekkürler. Benim ikamelerimde çok fazla çalışıyorum gibi görünebilir, ama iş arkadaşlarım için bir eğitim yapıyorum ve örneklerin hepsi biraz tartışmalı. – Vaccano