2008-10-05 28 views
24

Tôi đang cố gắng để Unit Test một lớp có nhiều chức năng nội bộ. Đây rõ ràng là cần thử nghiệm, nhưng dự án thử nghiệm của tôi là riêng biệt, chủ yếu là bởi vì nó bao gồm nhiều dự án nhỏ, liên quan. Những gì tôi có cho đến thời điểm này là:Truy cập các thành viên nội bộ thông qua System.Reflection?

FieldInfo[] _fields = 
    typeof(ButtonedForm.TitleButton).GetFields(
     BindingFlags.NonPublic | BindingFlags.Instance | 
     BindingFlags.DeclaredOnly); 
Console.WriteLine("{0} fields:", _fields.Length); 
foreach (FieldInfo fi in _fields) 
{ 
    Console.WriteLine(fi.Name); 
} 

Điều này kích thích tất cả các thành viên riêng độc đáo nhưng vẫn không hiển thị nội bộ. Tôi biết điều này là có thể, bởi vì khi tôi đã rối tung xung quanh với các thử nghiệm autogenerated Visual Studio có thể sản xuất, nó hỏi về một cái gì đó để làm với hiển thị internals để dự án thử nghiệm. Vâng, bây giờ tôi đang sử dụng NUnit và thực sự thích nó, nhưng làm thế nào tôi có thể đạt được điều tương tự với nó?

Trả lời

32

Sẽ phù hợp hơn khi sử dụng thuộc tính InternalsVisibleTo để cấp quyền truy cập cho các thành viên nội bộ của hội đồng vào nhóm thử nghiệm đơn vị của bạn.

Dưới đây là một liên kết với một số thông tin bổ sung hữu ích và đi bộ qua:

Để thực sự trả lời câu hỏi của bạn ... nội bộ và được bảo vệ không được công nhận trong Reflection NET API. Đây là một báo giá từ MSDN:

Từ khóa C# được bảo vệ và nội bộ không có ý nghĩa trong IL và không được sử dụng trong API phản ánh. Các điều khoản tương ứng trong IL là Gia đình và Hội. Để xác định một phương thức nội bộ bằng cách sử dụng Reflection, sử dụng thuộc tính IsAssembly. Để xác định phương thức nội bộ được bảo vệ, hãy sử dụng IsFamilyOrAssembly.

+0

Tôi đồng ý với việc sử dụng InternalsVisibleTo, nhưng cũng xin cảm ơn câu trả lời :) –

+0

Không có vấn đề gì, thật tốt khi có lời giải thích thực sự ngay cả trong trường hợp sử dụng cụ thể của bạn. –

+2

Chỉ cần một FYI, trang được liên kết đến trong câu trả lời này là của tôi và URL của tôi đã thay đổi. Đó là lý do tại sao bạn có thể nhận được 404. Hãy thử liên kết cập nhật này http://jason.whitehorn.ws/2007/11/09/The-Wonders-Of-InternalsVisibleTo.aspx –

6

Thêm thuộc tính mức lắp ráp vào dự án chính của bạn, với tên Hội thi dự án thử nghiệm sẽ làm cho thành viên nội bộ hiển thị.

Ví dụ thêm dòng sau vào lắp ráp của bạn bên ngoài bất kỳ lớp:

[assembly: InternalsVisibleTo("AssemblyB")] 

Hoặc cho một mục tiêu cụ thể hơn:

[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")] 

Lưu ý, nếu lắp ráp ứng dụng của bạn có một cái tên mạnh, thử nghiệm của bạn lắp ráp cũng sẽ cần phải được đặt tên mạnh mẽ.

6

Tôi nghĩ bạn cần hỏi xem bạn có nên viết các bài kiểm tra đơn vị cho các phương pháp riêng tư không? Nếu bạn viết đơn vị kiểm tra cho các phương pháp công cộng của bạn, với một bảo hiểm mã 'hợp lý', không phải là bạn đã thử nghiệm bất kỳ phương pháp tư nhân cần phải được gọi là kết quả?

Thử nghiệm lấy mẫu cho phương pháp riêng tư sẽ làm cho các thử nghiệm trở nên giòn hơn. Bạn sẽ có thể thay đổi việc thực hiện bất kỳ phương thức riêng tư nào mà không vi phạm bất kỳ thử nghiệm nào.

Refs:

lĩnh vực

http://weblogs.asp.net/tgraham/archive/2003/12/31/46984.aspx http://richardsbraindump.blogspot.com/2008/08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13/85088.aspx

+0

Điều gì sẽ xảy ra khi lỗi trong các chức năng nhỏ hơn này xảy ra và đột nhiên 10 kiểm tra dừng lại? –

+0

Tùy thuộc vào tình huống mà tôi cho là, nhưng nó sẽ không dễ sử dụng hơn, ví dụ, đề nghị InternalsVisibleTo, để lộ chúng và viết nhiều thử nghiệm nhắm mục tiêu? –

+0

Tôi kiểm tra tất cả các phương pháp nội bộ của mình. Điều duy nhất có thể xảy ra với việc thử nghiệm là một chút lãng phí thời gian. –

6

Mã của bạn là chỉ hiển thị - vì vậy tôi hy vọng nó sẽ không hiển thị bất kỳ thành viên nội bộ, như lĩnh vực nên luôn luôn tin IMO. (Với ngoại lệ tiềm năng của các hằng số.)

Nút ButtonedForm.TitleButton có thực sự có bất kỳ trường không phải riêng tư nào không? Nếu bạn đang cố gắng tìm các phương thức nội bộ thì rõ ràng là bạn cần phải gọi số GetMethods (hoặc GetMembers) để truy cập chúng.

Như những người khác đã đề xuất, InternalsVisibleTo rất tiện dụng để thử nghiệm (và hầu như chỉ để thử nghiệm!). Đối với việc bạn nên thử nghiệm các phương pháp nội bộ - tôi chắc chắn thấy nó hữu ích để có thể làm như vậy. Tôi không coi đơn vị thử nghiệm là độc quyền thử nghiệm hộp đen. Thông thường, khi bạn biết rằng chức năng công cộng được thực hiện bằng cách sử dụng một vài phương thức nội bộ được kết nối một cách đơn giản, việc kiểm tra kỹ lưỡng từng phương pháp nội bộ và một số thử nghiệm "tích hợp giả" trên phương pháp công khai sẽ dễ dàng hơn.

+0

Bạn nói đúng, tôi nên đã gọi cho GetMethods() để bắt đầu. +1 ngày mai khi tôi lại nhận được nhiều phiếu bầu hơn. Tôi mới với toàn bộ sự phản ánh, bạn có thể nói không? : D Tôi đã có một ngôn ngữ kịch bản nhỏ trong các công trình đôi khi, tôi con số đó sẽ giúp tôi tăng tốc độ phản chiếu tốt và thực sự ... –

1

Một lý do để sử dụng InternalsVisible là trong hoàn cảnh của tôi. Chúng tôi mua mã nguồn để kiểm soát biểu đồ. Chúng tôi đã tìm thấy nơi chúng tôi cần thực hiện một số sửa đổi đối với việc kiểm soát nguồn đó và biên dịch phiên bản của riêng chúng tôi. Bây giờ để đảm bảo chúng tôi đã không phá vỡ bất cứ điều gì, có một số bài kiểm tra đơn vị tôi cần phải viết rằng cần truy cập vào một số lĩnh vực nội bộ.

Đây là trường hợp hoàn hảo mà InternalsVisible có ý nghĩa.

Tôi đã tự hỏi, tuy nhiên, bạn sẽ làm gì nếu bạn không có quyền truy cập vào nguồn? Làm thế nào bạn có thể nhận được đến một lĩnh vực nội bộ? .Net Reflector có thể thấy mã, nhưng tôi đoán nó chỉ là nhìn vào IL.

+0

Như một người khác được đề cập, trong các cấu trúc bên trong IL được gọi là Hội. Bạn có thể sử dụng System.Reflection để truy cập các biến Assembly –

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