2014-10-04 22 views
5

Tôi có lớp A mà tôi đang thử nghiệm đơn vị một phương pháp trên đó có lớp B làm tham số. Lớp B là những gì tôi đang cố gắng để thử ra, và nó là một lớp trừu tượng. Lớp học tương tự như dưới đây.Làm thế nào để bạn giả lập một lớp trừu tượng có chứa một phương pháp trừu tượng nội bộ bằng cách sử dụng Moq?

public abstract class B 
{ 
    internal abstract void DoSomething(); 
} 

Kiểm tra đơn vị của tôi sẽ như thế nào.

[TestMethod] 
public void ClassA_Add_TestSomething() 
{ 
    var classA = new A(); 
    var mock = new Mock<B>(); 

    classA.Add(mock.Object); 

    // Assertion 
} 

Tôi nhận được ngoại lệ sau.

Phương pháp thử TestSomething ném ngoại lệ:
System.ArgumentException: Loại để thử phải là một giao diện hoặc một lớp trừu tượng hoặc không niêm phong. ---> System.TypeLoadException: Phương thức 'DoSomething' trong loại 'Castle.Proxies.BProxy' từ assembly 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null' không có triển khai thực hiện.

Tôi có thể giải quyết vấn đề này bằng cách làm phương pháp ảo thay vì trừu tượng, nhưng đó không phải là những gì tôi muốn thực hiện với thiết kế API. Tôi cũng đã cố gắng cung cấp cho nó triển khai thông qua mock.Setup(m => m.DoSomething()) để không có kết quả. Điều này có thể với Moq, hay tôi sẽ phải tạo ra một lớp thử nghiệm cụ thể có nguồn gốc từ lớp trừu tượng B? Tôi muốn tránh tạo ra các loại cụ thể, loại thất bại một số mục đích của việc sử dụng một khuôn khổ nhạo báng hoặc cứng đầu, hoặc tôi có bị lừa dối ở đây không?

Chỉnh sửa Tôi đã phát hiện ra rằng nếu tôi thực hiện phương pháp public abstract vấn đề này không xảy ra. Vì vậy, tôi đoán câu hỏi thực sự là nếu điều này thậm chí có thể với một phương pháp nội bộ khi sử dụng InternalsVisibleTo và Moq.

+0

Tại sao bạn không thể sử dụng mock.Setup? – brz

+0

Tôi nhận được ngoại lệ cho dù tôi có sử dụng Thiết lập hay không. Trong bài kiểm tra đơn vị của tôi, tôi không quan tâm liệu 'B.DoSomething' có thực hiện hay không, mặc dù tôi hiểu tại sao nó lại cần một.Có thể tôi không sử dụng 'Setup' chính xác, nhưng những gì tôi đã thử là khá cơ bản' mock.Setup (m => m.DoSomething()). Gọi lại (() => {}); ' –

+4

Hãy xem xét cẩn thận tại sao bạn có phương thức 'abstract abstract' trên lớp public. Những người khác sẽ không thể triển khai phương thức trừu tượng vì nó không hiển thị với chúng. Có lẽ đây là những gì bạn muốn, mặc dù sau đó tôi sẽ khuyên bạn nên làm cho các nhà xây dựng nội bộ cũng như vậy không ai nhận được ý tưởng rằng họ có thể thực hiện các lớp trừu tượng. –

Trả lời

3

Cân nhắc kỹ tại sao bạn có phương thức internal abstract trên lớp công khai. Những người khác sẽ không thể triển khai phương thức trừu tượng vì nó không hiển thị với chúng. Có lẽ đây là những gì bạn muốn. Đôi khi, với những hạn chế về thiết kế khác nhau, đây là một cách tiếp cận hợp lệ. Nếu thư viện của bạn sẽ bị người khác tiêu thụ, tôi khuyên bạn ít nhất cũng nên làm cho các nhà xây dựng bên trong cũng như vậy không ai có ý tưởng rằng họ có thể triển khai lớp trừu tượng.

5

Moq dựa trên Castle Dynamic Proxy để triển khai mocks của nó. Khi chạy, một assembly mới được tạo và nạp vào AppDomain của bạn bằng Moq (tên DynamicProxyGenAssembly2 xuất hiện trong thông điệp ngoại lệ).

Vấn đề là lắp ráp này không thể truy cập các lớp nội bộ và thành viên của mã của bạn, bởi vì chúng không hiển thị bên ngoài hội đồng nơi bạn khai báo chúng.

Một workaround là để đánh dấu lắp ráp của bạn với InternalsVisibleToAttribute và chỉ định tên của assembly tạo động:

[InternalsVisibleTo("DynamicProxyGenAssembly2")] 

Tuy nhiên phải nhớ rằng giải pháp này dựa vào một chi tiết thực hiện, và có thể ngừng làm việc trong tương lai phiên bản.

+2

Điều này hữu ích nói chung, nhưng trong trường hợp của tôi, InternalsVisibleTo đã được áp dụng một cách thích hợp. Vấn đề là với Moq xử lý phương thức nội bộ trên một kiểu trừu tượng, cụ thể. Câu trả lời cuối cùng là như MikeZ đã gợi ý, đó là để suy nghĩ lại thiết kế. –

+1

Như @ DavidAnderson-DCOM đã đề cập, giải pháp này không hoạt động trong trường hợp này. Tôi có thể xác nhận điều này trong thử nghiệm của riêng tôi. –

Các vấn đề liên quan