Moq: การตั้งค่าไม่ถูกต้องสำหรับสมาชิกที่ไม่สามารถเขียนทับได้: x => x.GetByTitle (“ asdf”)


111

ไม่แน่ใจว่าฉันจะแก้ไขปัญหานี้ได้อย่างไรโดยพยายามทดสอบหน่วยในเมธอด "GetByTitle"

นี่คือคำจำกัดความของฉัน:

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);
}

การทดสอบหน่วย:

[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);
}

การดำเนินการทดสอบทำให้ฉันมีข้อผิดพลาด:

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

อัปเดต

[Setup]ลักษณะของฉัน:

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

     _articleManager = new ArticleManager(_mockDaoFactory.Object);    
}

2
คุณสร้างอินสแตนซ์_mockDaoFactoryและ_mockArticleDaoที่ไหนสักแห่ง? คุณล้อเลียนชั้นเรียนหรืออินเทอร์เฟซ
Tomas Aschan

ใช่ฉันล้อเลียน daofactory และ mockarticleDao ใน [Setup] โดยใช้อินเทอร์เฟซ DAO ทำโดยใช้คลาส
mrblah

@tomas ฉันอัปเดตคำถามของฉันด้วยรหัสการตั้งค่า
mrblah

2
ที่คุณสามารถดูในคำตอบของฉันคุณต้องทั้งเยาะเย้ยอินเตอร์เฟซ (นั่นคือสิ่งที่ผมขอแนะนำ) หรือเครื่องหมายของวิธีการGetByTitle virtual
Tomas Aschan

ดูเหมือนว่าบรรทัดแรกในการทดสอบของคุณสามารถย้ายไปที่ขั้นตอนการตั้งค่าได้ ... ?
Tomas Aschan

คำตอบ:


154

ในการควบคุมพฤติกรรมของวัตถุจำลอง (อย่างน้อยที่สุดใน Moq) คุณต้องล้อเลียนอินเทอร์เฟซหรือตรวจสอบให้แน่ใจว่าพฤติกรรมที่คุณพยายามควบคุมถูกทำเครื่องหมายเสมือน ในความคิดเห็นของคุณฉันเข้าใจดังนั้นการสร้างอินสแตนซ์ของ_mockArticleDaoจึงเสร็จสิ้นดังนี้:

_mockArticleDao = new Mock<ArticleDAO>();

หากคุณต้องการเก็บไว้คุณต้องทำเครื่องหมายGetArticleวิธีการvirtual:

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

มิฉะนั้น (และนี่คือสิ่งที่ฉันแนะนำ) ให้จำลองอินเทอร์เฟซแทน

_mockArticleDao = new Mock<IArticleDAO>();

แต่เนื่องจาก ArticleDAO สืบทอดมาจาก Generic .... ถ้าฉันเยาะเย้ยอินเทอร์เฟซวิธีการใน GenericNhibern จะไม่สามารถใช้ได้?
mrblah

เนื่องจากการเรียกไปยัง GetArticleDAO จากโรงงานส่งคืน ArticleDAO ไม่ใช่ IArticleDAO b / c articleDAO ยังผูกกับคลาสนามธรรมที่มีสิ่งที่มี nhibernate อยู่ด้วย
mrblah

2
หากคุณไม่สามารถเยาะเย้ยอินเทอร์เฟซได้แสดงว่าคุณอาจกำลังทดสอบสิ่งที่ไม่ถูกต้อง ... แต่ถึงกระนั้นการทำเครื่องหมายวิธีเสมือนจะช่วยแก้ปัญหาได้
Tomas Aschan

+1 Tomas ฉันต้องฉีดพารามิเตอร์เข้าไปใน ctor ดังนั้นในกรณีของฉันฉันต้องเยาะเย้ยคลาสจริงและตั้งค่าวิธีการเป็นเสมือนเพราะคุณไม่สามารถแทรกพารามิเตอร์ลงใน ctor ของอินเทอร์เฟซได้ นี่เป็นแนวทางที่ถูกต้องหรือไม่?
Houman

4
@Kave: ถ้าคุณจำเป็นต้องฉีดอะไรบางอย่างในคอนสตรัคเตอร์คุณกำลังทดสอบสิ่งที่ไม่ถูกต้อง เยาะเย้ยสิ่งที่คุณให้กับคอนสตรัคเตอร์ตั้งค่าพฤติกรรมและทดสอบว่าคลาสนี้ทำงานอย่างที่ควรจะเป็น หากคุณต้องการให้เขียนอินเทอร์เฟซใหม่ที่คุณทำให้ประเภท "ฉีด" ใช้งานเพื่อเข้าถึงลายเซ็นของวิธีการทั้งหมด
Tomas Aschan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.