หน่วยทดสอบวิธีการภายในใน VS2017 .Net Standard library


150

ฉันกำลังเล่นกับผู้สมัคร Release Studio 2017 ล่าสุดโดยสร้างไลบรารี. Net Standard 1.6 ฉันใช้ xUnit เพื่อทดสอบโค้ดของฉันและสงสัยว่าคุณยังสามารถทดสอบวิธีการภายในใน VS2017 ได้หรือไม่

ฉันจำได้ว่าคุณสามารถคลาส AssemblyInfo.cs บรรทัดทั้งหมดใน VS2015 ที่จะเปิดใช้งานโครงการที่ระบุเพื่อดูวิธีการภายใน

[assembly:InternalsVisibleTo("MyTests")]

เนื่องจากไม่มี AssemblyInfo.cs class ใน VS2017 .Net Standard project ฉันสงสัยว่าคุณยังสามารถทดสอบวิธีการภายในหน่วยได้หรือไม่?


3
คุณควรจะสามารถทดสอบโค้ดของคุณจากฟังก์ชั่นการมองเห็นจากภายนอกเพียงอย่างเดียว ท้ายที่สุดหากไม่มีเส้นทางตรรกะจากรหัสภายนอกสามารถเข้าถึงวิธีการภายในเหล่านั้นแล้วพวกเขาจะทำอะไรที่นั่นในสถานที่แรก?
เดวิด

3
@ David ฉันสามารถและทำสิ่งนี้ได้ แต่ฉันได้ทำการทดสอบหน่วยง่ายๆรอบ ๆ คลาสภายในก่อนหน้านี้ เพียงเพื่อให้ชัดเจนยิ่งขึ้นในการทดสอบ
Phil Murray

5
AFAIK คุณสามารถวางแอ็ตทริบิวต์นี้ในไฟล์อื่นนอกnamespaceบล็อกและควรคอมไพล์ AssemblyInfo.csไม่ควรมีอะไรที่มหัศจรรย์เกี่ยวกับ มันใช้งานไม่ได้? แน่นอนคุณต้องเพิ่มที่ถูกต้องเป็นไปตามข้อหรือใช้แอตทริบิวต์ที่มีคุณสมบัติครบถ้วนusing [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")]
Groo

1
@ David หากคุณกำลังสร้างห้องสมุดที่มีคลาสภายในและคุณจำเป็นต้องทดสอบและจำลองคลาสเหล่านี้InternalsVisibleToเป็นสิ่งสำคัญ - เช่นที่นี่ - stackoverflow.com/a/17574183/43453
PandaWood

คำตอบ:


210

อ้างอิงถึง. NET docs สำหรับInternalsVisibleToAttribute :

แอ็ตทริบิวต์ถูกนำไปใช้ในระดับการประกอบ ซึ่งหมายความว่าสามารถรวมไว้ที่จุดเริ่มต้นของไฟล์รหัสต้นฉบับหรือสามารถรวมอยู่ในไฟล์ AssemblyInfo ในโครงการ Visual Studio

กล่าวอีกนัยหนึ่งคุณสามารถวางไว้ในไฟล์. cs ที่กำหนดชื่อเองและควรจะทำงานได้ดี:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]

1
@PhilMurray: ยังดูเหมือนว่าจะมีการตั้งค่าที่จะช่วยให้คุณสามารถสร้าง "คลาสสิก" ซึ่งเป็นAssemblyInfo.csไฟล์เช่นอธิบายที่นี่ มิฉะนั้นคุณลักษณะทั้งหมดเช่น "คำอธิบาย" "ลิขสิทธิ์" และสิ่งอื่น ๆ จะถูกเก็บไว้ในไฟล์. csproj
Groo

43

ตามที่อธิบายไว้ที่นี่:

https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

เป็นไปได้ที่จะเพิ่มแอททริบิวที่มองเห็นได้ภายในไฟล์โครงการโดยการเพิ่ม ItemGroup อื่น:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

หรือแม้กระทั่ง:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

ฉันชอบวิธีแก้ปัญหานั้นเพราะไฟล์โครงการดูเหมือนจะเป็นสถานที่ที่เหมาะสมสำหรับการกำหนดข้อกังวลดังกล่าว


8

ในขณะที่คำตอบแรกนั้นสมบูรณ์ดี หากคุณรู้สึกว่าคุณยังคงต้องการทำสิ่งนี้ในต้นฉบับAssemblyInfoคุณสามารถเลือกที่จะไม่สร้างไฟล์อัตโนมัติและเพิ่มด้วยตนเอง

<PropertyGroup>
   <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

สำหรับข้อมูลเพิ่มเติม: https://stackoverflow.com/a/47075759/869033


5

แอ็ตทริบิวต์ "InternalsVisibleTo" เป็นกุญแจสำคัญในการทดสอบ "white-box" ใด ๆ (เทอมของทศวรรษที่ฉันเดา) การทดสอบสำหรับ. Net มันสามารถวางในไฟล์ c # ใด ๆ ที่มีคุณลักษณะ "แอสเซมบลี" ที่ด้านหน้า โปรดทราบว่า MS DOCs บอกว่าชื่อชุดประกอบจะต้องผ่านการรับรองโดยโทเค็นกุญแจสาธารณะหากมีการลงนาม บางครั้งมันใช้งานไม่ได้และต้องใช้กุญแจสาธารณะเต็มรูปแบบแทน การเข้าถึงภายในเป็นกุญแจสำคัญในการทดสอบระบบที่เกิดขึ้นพร้อมกันและในหลาย ๆ สถานการณ์ ดูhttps://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 ในหนังสือเล่มนี้ Meszaros อธิบายถึงรูปแบบการเข้ารหัสที่หลากหลายซึ่งโดยทั่วไปจะเป็นแนวทาง "Design For Test" เพื่อการพัฒนาโปรแกรม อย่างน้อยนั่นก็เป็นวิธีที่ฉันใช้มันในช่วงหลายปีที่ผ่านมา

เพิ่ม: ขออภัยฉันไม่ได้อยู่ที่นี่มาระยะหนึ่งแล้ว วิธีการหนึ่งเรียกว่า "การทดสอบคลาสย่อย" โดย Meszaros อีกครั้งหนึ่งต้องใช้ "internalsvisableto" เพื่อเข้าถึง internals ของคลาสฐาน นี่เป็นวิธีแก้ปัญหาที่ดี แต่ไม่ได้ผลสำหรับคลาสที่ปิดผนึก เมื่อฉันสอน "การออกแบบสำหรับการทดสอบ" ฉันแนะนำว่ามันเป็นหนึ่งในสิ่งที่จำเป็นต้องมี "pre-engineered" ลงในคลาสพื้นฐานเพื่อให้สามารถทดสอบได้ มันต้องกลายเป็นเรื่องทางวัฒนธรรมไปแล้ว ออกแบบคลาสพื้นฐาน "ฐาน" ที่ไม่ได้เปิดใช้งาน เรียกมันว่า UnsealedBaseClass หรือสิ่งที่เป็นที่รู้จักอย่างสม่ำเสมอ นี่คือคลาสที่จะคลาสย่อยสำหรับการทดสอบ มันเป็นคลาสย่อยเพื่อสร้างคลาสที่ปิดผนึกการผลิตซึ่งมักจะแตกต่างกันเฉพาะในตัวสร้างมัน exposes ฉันทำงานในอุตสาหกรรมนิวเคลียร์และข้อกำหนดการทดสอบนั้นได้รับการพิจารณาอย่างจริงจัง ดังนั้นฉันต้องคิดเกี่ยวกับสิ่งเหล่านี้ตลอดเวลา อย่างไรก็ตามการปล่อยให้ตะขอทดสอบในรหัสการผลิตไม่ถือเป็นปัญหาในสาขาของเราตราบใดที่มันเป็น "ภายใน" ในการใช้งาน. Net การแตกหักของการทดสอบไม่ได้มีบางอย่างที่ค่อนข้างลึกซึ้ง


1

อีกวิธีหนึ่งคือการใช้ 'wrapper' คลาสพับลิก TestMyFoo ภายในโครงการเป้าหมายที่มีวิธีสาธารณะและสืบทอดจากคลาสที่คุณต้องการทดสอบ (เช่น MyFoo) วิธีการสาธารณะเหล่านี้เพียงแค่เรียกผ่านเข้าสู่ชั้นฐานที่คุณต้องการทดสอบ

มันไม่ 'เหมาะ' เมื่อคุณจบการจัดส่งเบ็ดทดสอบในโครงการเป้าหมายของคุณ แต่พิจารณารถยนต์ที่เชื่อถือได้ที่ทันสมัยมาพร้อมกับพอร์ตการวินิจฉัยและอุปกรณ์อิเล็กทรอนิกส์ที่เชื่อถือได้ที่ทันสมัยด้วยการเชื่อมต่อ JTAG แต่ไม่มีใครโง่พอที่จะขับรถโดยใช้พอร์ตการวินิจฉัย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.