การทดสอบหน่วยวิธีส่วนตัวใน C #


292

Visual Studio อนุญาตให้ทดสอบหน่วยวิธีการส่วนตัวผ่านคลาส accessor ที่สร้างขึ้นโดยอัตโนมัติ ฉันได้เขียนการทดสอบของวิธีการส่วนตัวที่รวบรวมเรียบร้อยแล้ว แต่ล้มเหลวขณะใช้งานจริง โค้ดในเวอร์ชันที่ค่อนข้างน้อยและการทดสอบคือ:

//in project MyProj
class TypeA
{
    private List<TypeB> myList = new List<TypeB>();

    private class TypeB
    {
        public TypeB()
        {
        }
    }

    public TypeA()
    {
    }

    private void MyFunc()
    {
        //processing of myList that changes state of instance
    }
}    

//in project TestMyProj           
public void MyFuncTest()
{
    TypeA_Accessor target = new TypeA_Accessor();
    //following line is the one that throws exception
    target.myList.Add(new TypeA_Accessor.TypeB());
    target.MyFunc();

    //check changed state of target
}

ข้อผิดพลาดรันไทม์คือ:

Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.

ตาม intellisense - และด้วยเหตุนี้ฉันเดาผู้รวบรวม - เป้าหมายเป็นประเภท TypeA_Accessor แต่ ณ รันไทม์มันเป็นประเภท TypeA และด้วยเหตุนี้รายการเพิ่มล้มเหลว

มีวิธีใดที่ฉันสามารถหยุดข้อผิดพลาดนี้ได้บ้าง หรืออาจเป็นไปได้มากกว่าที่คำแนะนำอื่น ๆ ที่คนอื่นมี (ฉันคาดเดาว่าอาจ "ไม่ทดสอบวิธีการส่วนตัว" และ "ไม่มีการทดสอบหน่วยจัดการกับสถานะของวัตถุ")


คุณต้องมี accessor สำหรับคลาส B ของเอกชน Accessor TypeA_Accessor ให้การเข้าถึงวิธีการส่วนตัวและการป้องกันของ TypeA อย่างไรก็ตาม TypeB ไม่ใช่วิธีการ มันเป็นคลาส
Dima

Accessor จัดเตรียมการเข้าถึงวิธีการส่วนตัว / ที่ได้รับการป้องกันสมาชิกคุณสมบัติและเหตุการณ์ต่างๆ ไม่ให้การเข้าถึงคลาสส่วนตัว / ที่มีการป้องกันภายในชั้นเรียนของคุณ และคลาสส่วนตัว / ที่มีการป้องกัน (TypeB) มีวัตถุประสงค์เพื่อใช้โดยวิธีการเป็นเจ้าของคลาส (TypeA) เท่านั้น โดยพื้นฐานแล้วคุณกำลังพยายามเพิ่มคลาสส่วนตัว (TypeB) จากนอก TypeA เป็น "myList" ซึ่งเป็นแบบส่วนตัว เนื่องจากคุณใช้ accessor จึงไม่มีปัญหาในการเข้าถึง myList อย่างไรก็ตามคุณไม่สามารถใช้ TypeB ผ่าน accessor โซลูชันที่เป็นไปได้จะย้าย TypeB นอก TypeA แต่มันสามารถทำลายการออกแบบของคุณ
Dima

รู้สึกว่าการทดสอบวิธีส่วนตัวควรทำโดย stackoverflow.com/questions/250692/…
nate_weldon

คำตอบ:


275

ใช่ไม่ต้องทดสอบวิธีการส่วนตัว .... แนวคิดของการทดสอบหน่วยคือการทดสอบหน่วยโดย 'API' สาธารณะ

หากคุณพบว่าคุณจำเป็นต้องทดสอบพฤติกรรมส่วนตัวหลายอย่างน่าจะเป็นไปได้ว่าคุณมี 'คลาส' ซ่อนตัวอยู่ในชั้นเรียนที่คุณพยายามทดสอบแยกและทดสอบโดยอินเทอร์เฟซสาธารณะ

คำแนะนำ / เครื่องมือคิดชิ้นเดียว ..... มีแนวคิดว่าไม่มีวิธีใดที่ควรเป็นแบบส่วนตัว ความหมายของวิธีการทั้งหมดควรอยู่บนส่วนต่อประสานสาธารณะของวัตถุ .... ถ้าคุณรู้สึกว่าคุณต้องทำให้มันเป็นส่วนตัวมันน่าจะมีชีวิตอยู่บนวัตถุอื่น

คำแนะนำชิ้นนี้ไม่ค่อยได้ผลนักในทางปฏิบัติ แต่คำแนะนำที่ดีส่วนใหญ่และบ่อยครั้งที่มันจะผลักดันผู้คนให้ย่อยสลายวัตถุของพวกเขาเป็นวัตถุขนาดเล็ก


386
ฉันไม่เห็นด้วย. ใน OOD วิธีการและคุณสมบัติส่วนตัวเป็นวิธีที่ไม่ควรทำซ้ำตัวเอง ( en.wikipedia.org/wiki/Don%27t_repeat_yourself ) แนวคิดเบื้องหลังการเขียนโปรแกรมกล่องดำและการห่อหุ้มคือการซ่อนรายละเอียดทางเทคนิคจากผู้สมัครสมาชิก ดังนั้นจึงจำเป็นต้องมีวิธีการและคุณสมบัติส่วนตัวที่ไม่สำคัญในรหัสของคุณ และถ้ามันไม่ไร้สาระก็จะต้องมีการทดสอบ
AxD

8
มันไม่ได้เป็นอย่างแท้จริงบางภาษา OO ไม่มีวิธีส่วนตัวคุณสมบัติส่วนตัวสามารถมีวัตถุที่มีส่วนต่อประสานสาธารณะซึ่งสามารถทดสอบได้
Keith Nicholas

7
ประเด็นของคำแนะนำนี้คือถ้าคุณทำสิ่งหนึ่งและเป็น DRY แล้วก็มีเหตุผลเล็กน้อยที่จะมีวิธีการส่วนตัว บ่อยครั้งที่วิธีการส่วนตัวทำสิ่งที่วัตถุไม่รับผิดชอบ แต่มีประโยชน์มากหากไม่ใช่เรื่องไร้สาระโดยทั่วไปแล้วมันเป็นอีกวัตถุหนึ่งที่น่าจะละเมิด SRP
Keith Nicholas

28
ไม่ถูกต้อง. คุณอาจต้องการใช้วิธีการส่วนตัวเพื่อหลีกเลี่ยงการทำสำเนารหัส หรือสำหรับการตรวจสอบ หรือเพื่อวัตถุประสงค์อื่น ๆ อีกมากมายที่โลกสาธารณะไม่ควรรู้
Jorj

37
เมื่อคุณถูกทิ้งในฐานข้อมูล OO ดังนั้นการออกแบบที่น่ากลัวและขอให้ "ปรับปรุงแบบค่อยเป็นค่อยไป" มันเป็นความผิดหวังที่พบว่าฉันไม่สามารถทำการทดสอบครั้งแรกสำหรับวิธีการส่วนตัว ใช่บางทีในตำราเรียนวิธีการเหล่านี้จะไม่ได้อยู่ที่นี่ แต่ในโลกแห่งความจริงเรามีผู้ใช้ที่มีความต้องการผลิตภัณฑ์ ฉันไม่สามารถทำการรีแฟคเตอร์ "Look at clean clean" จำนวนมหาศาลได้โดยไม่ต้องทำการทดสอบในโครงการเพื่อสร้างออกมา รู้สึกเหมือนเป็นอีกตัวอย่างหนึ่งของการบังคับให้ฝึกโปรแกรมเมอร์ให้เข้าสู่ถนนหนทางที่ไร้เดียงสาดูดี แต่ไม่คำนึงถึงความยุ่งเหยิงที่แท้จริง
dune.rocks

666

คุณสามารถใช้คลาส PrivateObject

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(expectedVal, retVal);

25
นี่คือคำตอบที่ถูกต้องตอนนี้ Microsoft ได้เพิ่ม PrivateObject แล้ว
Zoey

4
คำตอบที่ดี แต่โปรดทราบว่า PrivateMethod จำเป็นต้อง "ป้องกัน" แทน "ส่วนตัว"
HerbalMart

23
@ HerbalMart: บางทีฉันเข้าใจผิดคุณ แต่ถ้าคุณแนะนำว่า PrivateObject สามารถเข้าถึงสมาชิกที่ได้รับความคุ้มครองและไม่ใช่สมาชิกส่วนตัวคุณเข้าใจผิด
kmote

17
@JeffPearce สำหรับวิธีการคงที่คุณสามารถใช้ "PrivateType pt = new PrivateType (typeof (MyClass));" แล้วเรียก InvokeStatic บนวัตถุ pt ตามที่คุณจะเรียกใช้ Invoke บนวัตถุส่วนตัว
Steve Hibbert

12
ในกรณีที่ทุกคนสงสัยว่าเป็น MSTest.TestFramework v1.2.1 - คลาส PrivateObject และ PrivateType ไม่พร้อมใช้งานสำหรับโครงการที่กำหนดเป้าหมาย. NET Core 2.0 - มีปัญหา github สำหรับเรื่องนี้: github.com/Microsoft/testfx/issues/366
shiitake

98

“ ไม่มีอะไรที่เรียกว่าเป็นมาตรฐานหรือแนวปฏิบัติที่ดีที่สุดบางทีพวกเขาอาจเป็นแค่ความคิดเห็นยอดนิยม”

กันถือเป็นจริงสำหรับการสนทนานี้เช่นกัน

ป้อนคำอธิบายรูปภาพที่นี่

ทุกอย่างขึ้นอยู่กับสิ่งที่คุณคิดว่าเป็นหน่วยถ้าคุณคิดว่า UNIT เป็นชั้นเรียนคุณจะต้องใช้วิธีการสาธารณะเท่านั้น หากคุณคิดว่า UNIT เป็นบรรทัดของการกดปุ่มวิธีส่วนตัวจะไม่ทำให้คุณรู้สึกผิด

ถ้าคุณต้องการเรียกใช้เมธอดส่วนตัวคุณสามารถใช้คลาส "PrivateObject" และเรียกใช้เมธอดที่เรียกใช้ คุณสามารถรับชมวิดีโอ youtube แบบเจาะลึกนี้ ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) ซึ่งแสดงวิธีใช้ "PrivateObject" และยังกล่าวถึงว่าการทดสอบวิธีส่วนตัวนั้นมีเหตุผลหรือไม่


55

อีกความคิดหนึ่งคือการขยายการทดสอบไปยังคลาส / วิธีการ "ภายใน" ซึ่งให้ความรู้สึกแบบกล่องสีขาวของการทดสอบนี้มากขึ้น คุณสามารถใช้ InternalsVisibleToAttribute ในแอสเซมบลีเพื่อแสดงสิ่งเหล่านี้เพื่อแยกโมดูลทดสอบหน่วย

เมื่อใช้ร่วมกับคลาสที่ปิดผนึกคุณสามารถเข้าใกล้แค็ปซูลแบบนั้นซึ่งวิธีการทดสอบนั้นสามารถมองเห็นได้จากการประกอบวิธีที่ไม่ใช้ พิจารณาว่าวิธีการป้องกันในชั้นเรียนที่ปิดสนิทนั้นเป็นเรื่องส่วนตัว

[assembly: InternalsVisibleTo("MyCode.UnitTests")]
namespace MyCode.MyWatch
{
    #pragma warning disable CS0628 //invalid because of InternalsVisibleTo
    public sealed class MyWatch
    {
        Func<DateTime> _getNow = delegate () { return DateTime.Now; };


       //construktor for testing purposes where you "can change DateTime.Now"
       internal protected MyWatch(Func<DateTime> getNow)
       {
           _getNow = getNow;
       }

       public MyWatch()
       {            
       }
   }
}

และทดสอบหน่วย:

namespace MyCode.UnitTests
{

[TestMethod]
public void TestminuteChanged()
{
    //watch for traviling in time
    DateTime baseTime = DateTime.Now;
    DateTime nowforTesting = baseTime;
    Func<DateTime> _getNowForTesting = delegate () { return nowforTesting; };

    MyWatch myWatch= new MyWatch(_getNowForTesting );
    nowforTesting = baseTime.AddMinute(1); //skip minute
    //TODO check myWatch
}

[TestMethod]
public void TestStabilityOnFebruary29()
{
    Func<DateTime> _getNowForTesting = delegate () { return new DateTime(2024, 2, 29); };
    MyWatch myWatch= new MyWatch(_getNowForTesting );
    //component does not crash in overlap year
}
}

ฉันไม่แน่ใจว่าฉันเข้าใจ InternalsVisibleToAttribute ทำให้วิธีการและคุณลักษณะที่ถูกทำเครื่องหมายเป็น "ภายใน" สามารถเข้าถึงได้ แต่เขตข้อมูลและวิธีการของฉันเป็น "ส่วนตัว" คุณแนะนำให้ฉันเปลี่ยนสิ่งต่าง ๆ จากการเป็นส่วนตัวเป็นภายในหรือไม่? ฉันคิดว่าฉันเข้าใจผิด
Junichiro

2
ใช่นั่นคือสิ่งที่ฉันแนะนำ มันค่อนข้าง "แฮ็ค" แต่อย่างน้อยพวกเขาก็ไม่ได้เป็น "สาธารณะ"
Jeff

27
นี่เป็นคำตอบที่ยอดเยี่ยมเพียงเพราะมันไม่ได้พูดว่า "อย่าทดสอบวิธีการส่วนตัว" แต่ใช่มันค่อนข้าง "แฮ็ค" ฉันหวังว่าจะมีทางออก IMO เป็นการดีที่จะพูดว่า "วิธีการส่วนตัวไม่ควรทดสอบ" เพราะวิธีที่ฉันเห็น: เทียบเท่ากับ "วิธีการส่วนตัวไม่ควรถูกต้อง"
MasterMastic

5
ใช่เคนฉันยังสับสนโดยผู้ที่อ้างว่าวิธีการส่วนตัวไม่ควรทดสอบในการทดสอบหน่วย API สาธารณะเป็นผลลัพธ์ แต่บางครั้งการใช้งานผิดก็ให้ผลลัพธ์ที่ถูกต้องเช่นกัน หรือการนำไปใช้นั้นมีผลข้างเคียงที่ไม่ดีเช่นการถือครองทรัพยากรที่ไม่จำเป็นการอ้างอิงวัตถุที่ป้องกันไม่ให้ถูกรวบรวมโดย gc ... ฯลฯ ถ้าพวกเขามีการทดสอบอื่น ๆ ที่สามารถครอบคลุมวิธีการส่วนตัวมากกว่าการทดสอบหน่วยมิฉะนั้นฉันจะพิจารณาว่าพวกเขาไม่สามารถรักษารหัสทดสอบ 100%
m.P.Pony

ฉันเห็นด้วยกับ MasterMastic นี่ควรเป็นคำตอบที่ยอมรับได้
XDS

27

วิธีหนึ่งในการทดสอบวิธีการส่วนตัวคือผ่านการไตร่ตรอง สิ่งนี้ใช้ได้กับ NUnit และ XUnit เช่นกัน:

MyObject objUnderTest = new MyObject();
MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = {"parameters here"};
methodInfo.Invoke(objUnderTest, parameters);

call methods คงที่และไม่คงที่ ?
Kiquenet

2
ข้อเสียของวิธีการพึ่งพาการสะท้อนคือพวกเขามักจะแตกเมื่อคุณเปลี่ยนชื่อวิธีการใช้ R # มันอาจจะไม่ใช่ปัญหาใหญ่สำหรับโครงการขนาดเล็ก แต่ในรหัสฐานขนาดใหญ่มันจะกลายเป็นการจู้จี้แบบทดสอบหน่วยแตกในแบบนั้นแล้วต้องไปรอบ ๆ และแก้ไขได้อย่างรวดเร็ว ในแง่นี้ฉันเงินของฉันไปที่คำตอบของเจฟฟ์
XDS

2
@XDS ชื่อที่แย่เกินไป () ไม่ทำงานเพื่อรับชื่อของวิธีการส่วนตัวจากนอกคลาส
Gabriel Morin

12

เอ่อ ... มาที่นี่พร้อมกับปัญหาเดียวกันทั้งหมด: ทดสอบวิธีส่วนตัวที่เรียบง่ายแต่สำคัญ หลังจากอ่านกระทู้นี้ดูเหมือนว่า "ฉันต้องการเจาะรูเรียบง่ายนี้ในชิ้นส่วนโลหะที่เรียบง่ายนี้และฉันต้องการให้แน่ใจว่าคุณภาพตรงตามข้อกำหนด" แล้วก็มา"โอเคนี่ไม่ใช่เรื่องง่าย ก่อนอื่นไม่มีเครื่องมือที่เหมาะสมในการทำเช่นนั้น แต่คุณสามารถสร้างหอดูดาวคลื่นความโน้มถ่วงในสวนของคุณอ่านบทความของฉันที่http://foobar.brigther-than-einstein.org/แน่นอนคุณ ต้องเข้าร่วมหลักสูตรฟิสิกส์ควอนตัมขั้นสูงบางอย่างจากนั้นคุณต้องใช้ไนโตรเจนพิเศษที่เย็นมากและแน่นอนหนังสือของฉันมีให้ที่ Amazon "...

กล่าวอีกนัยหนึ่ง ...

ไม่สิ่งแรกเลย

วิธีการแต่ละคนและทุกอาจเป็นส่วนตัวภายในได้รับการคุ้มครองประชาชนมีที่จะทดสอบ จะต้องมีวิธีที่จะใช้การทดสอบดังกล่าวโดยไม่ต้องกังวลใจเช่นที่นำเสนอที่นี่

ทำไม? เพราะแน่นอนของสถาปัตยกรรมกล่าวทำเพื่อให้ห่างไกลจากผู้ร่วมสมทบบางส่วน บางทีการพูดซ้ำอย่างง่าย ๆ ของหลักการซอฟต์แวร์อาจทำให้เข้าใจถึงข้อผิดพลาดบางอย่างได้

ในกรณีนี้ผู้ต้องสงสัยปกติคือ: OCP, SRP และเช่นเคย KIS

แต่เดี๋ยวก่อน ความคิดที่จะทำให้ทุกอย่างที่มีต่อสาธารณะนั้นเป็นเรื่องของการเมืองน้อยลงและทัศนคติ แต่. เมื่อพูดถึงโค้ดแม้แต่ในชุมชนโอเพ่นซอร์สแล้วนี่ไม่ใช่ความเชื่อ แต่การซ่อนบางสิ่งเป็นการปฏิบัติที่ดีเพื่อให้คุ้นเคยกับ API บางอย่างได้ง่ายขึ้น ตัวอย่างเช่นคุณจะซ่อนการคำนวณที่สำคัญมากของการสร้างบล็อกเทอร์โมมิเตอร์ระบบดิจิตอลรุ่นใหม่ออกสู่ตลาดของคุณ - เพื่อไม่ซ่อนคณิตศาสตร์หลังเส้นโค้งที่วัดได้จริงไปยังเครื่องอ่านรหัสที่อยากรู้อยากเห็น แต่เพื่อป้องกันโค้ดของคุณขึ้นอยู่กับ บางทีผู้ใช้ที่สำคัญก็ไม่สามารถต้านทานการใช้รหัสส่วนตัวของคุณภายในป้องกันก่อนที่จะใช้ความคิดของตัวเอง

ฉันกำลังพูดถึงอะไร

ส่วนตัวคู่ TranslateMeasurementIntoLinear (doubleMeMementment จริง);

มันง่ายที่จะประกาศอายุของชาวกุมภ์หรือสิ่งที่ถูกเรียกในปัจจุบัน แต่ถ้าชิ้นส่วนของเซ็นเซอร์ของฉันได้รับจาก 1.0 ถึง 2.0 การใช้งานของ Translate ... อาจเปลี่ยนจากสมการเชิงเส้นง่าย ๆ ที่เข้าใจได้ง่ายและ "re- ใช้งานได้ "สำหรับทุกคนเพื่อการคำนวณที่ซับซ้อนที่ใช้การวิเคราะห์หรืออะไรก็ตามดังนั้นฉันจะทำลายรหัสของคนอื่น ทำไม? เนื่องจากพวกเขาไม่เข้าใจการเข้ารหัสซอฟต์แวร์ที่ล้ำค่ามากแม้แต่ KIS

เพื่อทำให้เทพนิยายนี้สั้น: เราต้องการวิธีง่ายๆในการทดสอบวิธีการส่วนตัวโดยไม่ต้องกังวลใจ

ครั้งแรก: สวัสดีปีใหม่ทุกคน!

ประการที่สอง: ทบทวนบทเรียนสถาปนิกของคุณ

ประการที่สาม: ตัวแก้ไข "สาธารณะ" คือศาสนาไม่ใช่วิธีแก้ปัญหา


5

ตัวเลือกอื่นที่ไม่ได้กล่าวถึงเพียงแค่สร้างคลาสการทดสอบหน่วยเป็นลูกของวัตถุที่คุณกำลังทดสอบ ตัวอย่าง NUnit:

[TestFixture]
public class UnitTests : ObjectWithPrivateMethods
{
    [Test]
    public void TestSomeProtectedMethod()
    {
        Assert.IsTrue(this.SomeProtectedMethod() == true, "Failed test, result false");
    }
}

วิธีนี้จะทำให้การทดสอบส่วนตัวและการป้องกัน (แต่ไม่ใช่การสืบทอดส่วนตัว) ง่ายและวิธีนี้จะช่วยให้คุณแยกการทดสอบทั้งหมดออกจากรหัสจริงเพื่อที่คุณจะไม่ได้ปรับใช้ชุดประกอบการทดสอบกับการผลิต การเปลี่ยนวิธีการส่วนตัวของคุณเป็นวิธีที่ได้รับการป้องกันจะยอมรับได้ในวัตถุที่สืบทอดมาจำนวนมากและเป็นการเปลี่ยนแปลงที่ทำได้ง่าย

อย่างไรก็ตาม ...

ในขณะที่นี่เป็นวิธีที่น่าสนใจในการแก้ปัญหาของวิธีทดสอบวิธีซ่อนเร้นฉันไม่แน่ใจว่าฉันจะสนับสนุนว่านี่เป็นวิธีการแก้ไขปัญหาที่ถูกต้องในทุกกรณี ดูเหมือนแปลกเล็กน้อยที่จะทำการทดสอบภายในวัตถุและฉันสงสัยว่าอาจมีบางสถานการณ์ที่วิธีการนี้จะทำให้คุณตกใจ (เช่นวัตถุที่ไม่เปลี่ยนรูปอาจทำให้การทดสอบบางอย่างยาก)

ในขณะที่ฉันพูดถึงวิธีการนี้ฉันขอแนะนำว่านี่เป็นคำแนะนำในการระดมสมองมากกว่าโซลูชันที่ถูกกฎหมาย เอาไปด้วยเม็ดเกลือ

แก้ไข: ฉันพบว่าเฮฮาอย่างแท้จริงที่ผู้คนโหวตให้คำตอบนี้เพราะฉันอธิบายอย่างชัดเจนว่าเป็นความคิดที่ไม่ดี นั่นหมายความว่าผู้คนเห็นด้วยกับฉันหรือไม่ ฉันสับสนมาก .....


มันเป็นทางออกที่สร้างสรรค์ แต่แฮ็คก็ใจดี
shinzou

3

จากหนังสือทำงานอย่างมีประสิทธิภาพด้วยรหัสมรดก :

"ถ้าเราต้องการทดสอบวิธีการส่วนตัวเราควรทำให้เป็นสาธารณะถ้าทำให้สาธารณะเป็นส่วนที่รบกวนเราในกรณีส่วนใหญ่ก็หมายความว่าชั้นเรียนของเราทำมากเกินไปและเราควรแก้ไข"

วิธีการแก้ไขตามผู้สร้างคือการสร้างคลาสใหม่และเพิ่มวิธีการเป็น publicวิธีการแก้ไขได้ตามที่ผู้เขียนเป็นโดยการสร้างคลาสใหม่และการเพิ่มวิธีการเป็น

ผู้เขียนอธิบายเพิ่มเติม:

"การออกแบบที่ดีสามารถทดสอบได้และการออกแบบที่ไม่สามารถทดสอบได้ไม่ดี"

ดังนั้นภายในข้อ จำกัด เหล่านี้ตัวเลือกที่แท้จริงของคุณคือการสร้างวิธีการpublicไม่ว่าจะเป็นในปัจจุบันหรือคลาสใหม่


2

TL; DR:แยกเมธอดไพรเวตไปยังคลาสอื่น, ทดสอบกับคลาสนั้น; อ่านเพิ่มเติมเกี่ยวกับหลักการ SRP (หลักการความรับผิดชอบเดี่ยว)

ดูเหมือนว่าคุณต้องการแยกไปยังprivateวิธีการในชั้นอื่น publicในการนี้ควรจะเป็น แทนที่จะพยายามทดสอบบนprivateวิธีนี้คุณควรทดสอบpublicวิธีการเรียนอื่นนี้

เรามีสถานการณ์ต่อไปนี้:

Class A
+ outputFile: Stream
- _someLogic(arg1, arg2) 

เราจำเป็นต้องทดสอบตรรกะของ_someLogic; แต่ดูเหมือนว่าClass Aจะมีบทบาทมากกว่าที่ต้องการ (ละเมิดหลักการ SRP); เพียงแค่ปรับโครงสร้างเป็นสองคลาส

Class A1
    + A1(logicHandler: A2) # take A2 for handle logic
    + outputFile: Stream
Class A2
    + someLogic(arg1, arg2) 

ด้วยวิธีนี้someLogicสามารถทดสอบใน A2; ใน A1 เพียงแค่สร้างบาง A2 ปลอมแล้วฉีดให้กับตัวสร้างการทดสอบที่ A2 someLogicเรียกว่าฟังก์ชั่นที่มีชื่อว่า


0

ใน VS 2005/2008 คุณสามารถใช้accessor ส่วนตัวเพื่อทดสอบสมาชิกส่วนตัวได้ แต่วิธีนี้จะหายไปใน VS รุ่นที่ใหม่กว่า


1
คำตอบที่ดีในปี 2008 ถึงต้นปี 2010 ตอนนี้โปรดดูตัวเลือก PrivateObject และ Reflection (ดูคำตอบหลายข้อด้านบน) VS2010 มีข้อผิดพลาดของ accessor, MS เลิกใช้แล้วใน VS2012 นอกจากว่าคุณจะถูกบังคับให้อยู่ใน VS2010 หรือมากกว่า (มากกว่า 18 ปีขึ้นไป) โปรดประหยัดเวลาด้วยการหลีกเลี่ยงการเข้าถึงส่วนตัว :-)
Zephan Schroeder
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.