Moq: Geçersiz kılınamayan bir üyede geçersiz kurulum: x => x.GetByTitle ("asdf")


111

Bunu nasıl düzeltebileceğimden emin değilim, "GetByTitle" yönteminde bir birim testi yapmaya çalışıyorum

İşte tanımlarım:

public class ArticleDAO :  GenericNHibernateDAO(IArticle, int>, IArticleDAO
{
    public IArticle GetByTitle(string title)
    {
        IQuery query = Session.CreateQuery("...")
        return query.UniqueResult<IArticle>();
    }
}

public interface IArticleDAO
{
    IArticle GetByTitle(string title);
}

ünite testi:

[Test]
public void can_load_by_title()
{
    _mockDaoFactory.Setup(x => x.GetArticleDao())
                                .Returns(_mockArticleDao.Object);
    _mockArticleDao.Setup(x => x.GetByTitle("some title"))
                                .Returns(article1.Object);

    _articleManager.LoadArticle("some title");

    Assert.IsNotNull(_articleManager.Article);
}

Testi çalıştırmak bana şu hatayı veriyor:

System.ArgumentException: Invalid setup on a non-overridable member:
x => x.GetByTitle("some title")

Güncelleme

Benim [Setup]görünüyor gibi:

[Setup]
public void SetUp()
{
     _mockDaoFactory = new Mock<IDaoFactory>();
     _mockArticleDao = new Mock<ArticleDao>();

     _articleManager = new ArticleManager(_mockDaoFactory.Object);    
}

2
Örnek veriyor musunuz _mockDaoFactoryve bir _mockArticleDaoyerde?
Sınıfla

Evet, Arabirimi kullanarak [Kurulum] 'da arka plan ve alay konusudao ile alay ettim. DAO, sınıf kullanılarak yapıldı.
mrblah

@tomas Sorum kurulum koduyla güncelledim.
mrblah

2
Cevabımda görebileceğiniz gibi, ya arayüzle dalga geçmeniz (tavsiye ettiğim şey budur) ya da GetByTitleyöntemi işaretlemeniz gerekir virtual.
Tomas Aschan

Ayrıca, testinizin ilk satırı kurulum rutinine taşınmış gibi görünüyor ...?
Tomas Aschan

Yanıtlar:


154

Sahte bir nesnenin davranışını kontrol etmek için (en azından Moq'da), bir arabirimle dalga geçmeniz veya kontrol etmeye çalıştığınız davranışın sanal olarak işaretlendiğinden emin olmanız gerekir. Yorumunuzda, örneğinin _mockArticleDaoşu şekilde yapılması için anlıyorum :

_mockArticleDao = new Mock<ArticleDAO>();

Böyle kalmasını istiyorsanız, GetArticleyöntemi işaretlemeniz gerekir virtual:

public class ArticleDAO :  GenericNHibernateDAO(IArticle, int>, IArticleDAO
{
    public virtual IArticle GetByTitle(string title)
    {
        // ...
    }
}

Aksi takdirde (ve önerdiğim şey budur), bunun yerine arayüzle alay edin.

_mockArticleDao = new Mock<IArticleDAO>();

ancak ArticleDAO Generic .... 'den miras aldığından, eğer arayüzde GenericNhibern' deki metotlarla dalga geçersem. mevcut olmayacak mı?
mrblah

Fabrikadan GetArticleDAO'ya yapılan çağrı, IArticleDAO değil ArticleDAO'yu döndürdüğü için, b / c makaleDAO, içinde hiçbir şey bulunmayan soyut bir sınıfa da bağlanır.
mrblah

2
Arayüzle dalga geçemiyorsanız, yanlış şeyi test ediyor olabilirsiniz ... ancak yine de yöntemi sanal olarak işaretlemek sorunu çözecektir.
Tomas Aschan

+1 Tomas, ctor'a bir parametre enjekte etmem gerekiyor, bu yüzden benim durumumda gerçek sınıfla dalga geçmek ve yöntemleri sanal olarak ayarlamak zorunda kaldım çünkü bir Interface'in ctor'una parametreleri enjekte edemezsin. Bu doğru bir yaklaşım mı?
Houman

4
@Kave: Yapıcıya bir şey enjekte etmeniz gerekiyorsa, kesinlikle yanlış şeyi test ediyorsunuz. Yapıcıya ne verirseniz verin, davranışını ayarlayın ve bu sınıfın olması gerektiği gibi davrandığını test edin . Gerekirse, tüm yöntem imzalarına erişmek için "enjekte" tipini uyguladığınız yeni bir arabirim yazın.
Tomas Aschan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.