Kako jedinica testirati statičke metode u C #

Kada gradite ili radite u .NET aplikacijama, često možete koristiti statičke metode. Metode u C # mogu biti statične ili nestatične. Nestatička metoda (poznata i kao metoda instance) može se pozvati na instanci klase kojoj pripada. Statičkim metodama nije potrebna instanca klase da bi se pozvale - one se mogu pozvati na samoj klasi.

Iako je testiranje nestatične metode (barem one koja ne poziva statičku metodu ili ne djeluje s vanjskim ovisnostima) jednostavno, testiranje statičke metode uopće nije lak zadatak. Ovaj članak govori o tome kako možete prevladati ovaj izazov i testirati statičke metode u C #. 

[Također na: Kako refaktorirati Božje objekte u C #]

Da biste radili s primjerima koda iz ovog članka, u sustavu biste trebali instalirati Visual Studio 2019. Ako još nemate kopiju, ovdje možete preuzeti Visual Studio 2019.  

Stvorite projekt aplikacije konzole .NET Core u Visual Studiju

Prvo stvorimo projekt .NET Core Console Application u Visual Studiju. Pod pretpostavkom da je Visual Studio 2019 instaliran u vašem sustavu, slijedite korake opisane u nastavku da biste u Visual Studiju stvorili novi projektni program konzole .NET Core.

  1. Pokrenite Visual Studio IDE.
  2. Kliknite "Stvori novi projekt".
  3. U prozoru "Stvori novi projekt" s popisa predložaka odaberite "Aplikacija konzole (.NET Core)".
  4. Kliknite Dalje.
  5. U sljedećem prozoru "Konfiguriranje novog projekta" navedite naziv i mjesto za novi projekt.
  6. Kliknite Stvori. 

To će stvoriti novi projektni program konzole .NET Core u Visual Studio 2019. Na sličan način izradite još dva projekta - knjižnicu klasa i projekt jedinstvenog testa (xUnit test). Ova tri projekta koristit ćemo za ilustraciju jediničnog testiranja statičkih metoda u sljedećim odjeljcima ovog članka.

Kada se statička metoda može, a ne može testirati jedinicom

Jedinstveno testiranje statičke metode ne razlikuje se od jedinstvenog testiranja nestatičke metode. Statičke metode same po sebi nisu neprovjerljive. Statička metoda koja ne sadrži stanje ili ne mijenja stanje može se testirati jedinicom. Sve dok su metoda i njene ovisnosti idempotentne, metoda se može jedinstveno testirati. Problemi nastaju kada statička metoda poziva druge metode ili kada objekt koji se testira poziva statičku metodu. S druge strane, ako objekt koji se testira poziva metodu instance, tada ga možete jednostavno testirati.

Statička metoda ne može se jedinično testirati ako vrijedi bilo što od sljedećeg: 

  • Statička metoda komunicira s vanjskim ovisnostima kao što su baza podataka, datotečni sustav, mreža ili vanjski API.
  • Statička metoda sadrži podatke o stanju, odnosno ako predmemorira podatke u statički objekt klase.

Razmotrite sljedeći isječak koda koji prikazuje dvije klase, naime ProductBL i Logger. Iako je ProductBL ne-statička klasa, Logger je statična klasa. Primijetite da je metoda Write klase Logger pozvana iz metode LogMessage klase ProductBL.

javna klasa ProductBL

    {

        javna void LogMessage (niz poruka)

        {

            Logger.Write (poruka);

        }

    }

    drvosječa javne klase

    {

        javna statička void Write (string poruka)

        {

           // Ovdje napišite svoj kod za zapis podataka

        }

    }

Pretpostavimo da se metoda Write klase Logger spaja na bazu podataka, a zatim zapisuje podatke u tablicu baze podataka. Ime baze podataka i njene tablice u koju bi podaci trebali biti upisani mogu biti unaprijed konfigurirani u datoteci appsettings.json. Kako sada možete napisati jedinične testove za ProductBL metodu?

Imajte na umu da se statičke metode ne mogu lako ismijati. Kao primjer, ako imate dvije klase s imenom A i B, a klasa A koristi statički član klase B, nećete moći jedinstveno testirati klasu A izolirano.

Tri načina za jedinstveno testiranje statičkih metoda

Moq možete koristiti za ruganje ne-statičkim metodama, ali se ne može koristiti za ruganje statičkim metodama. Iako se statičke metode ne mogu lako izrugivati, postoji nekoliko načina za ismijavanje statičkih metoda.

Možete iskoristiti Moles ili Fakes framework od Microsofta da biste se rugali pozivima statičkih metoda. (Okvir Fakes uključen je u Visual Studio 2012 kao nasljednik Molesa - to je sljedeća generacija Moles and Stubs.) Drugi način za ismijavanje poziva statičke metode je korištenje delegata. Postoji još jedan način za ismijavanje poziva statične metode u aplikaciji - pomoću klasa omota i ubrizgavanja ovisnosti.

IMHO je ova posljednja opcija najbolje rješenje problema. Sve što trebate je umotati poziv statičke metode u metodu instance, a zatim upotrijebiti injekciju ovisnosti za ubrizgavanje instance klase omota u klasu koja se ispituje.

Stvorite klasu omota u C #

Sljedeći isječak koda ilustrira klasu LogWrapper koja implementira sučelje IWrapper i omotava poziv metode Logger.Write () unutar metode instance koja se naziva LogData.

javna klasa LogWrapper: IWrapper

    {

        string _message = null;

        javni LogWrapper (niz poruka)

        {

            _poruka = ​​poruka;

        }

        javna void LogData (niz poruka)

        {

            _poruka = ​​poruka;

            Logger.Write (_poruka);

        }

    }

Sljedeći isječak koda prikazuje sučelje IWrapper. Sadrži deklaraciju metode LogData.

javno sučelje IWrapper

    {

        void LogData (niz poruka);

    }

Klasa ProductBL koristi ubrizgavanje ovisnosti (ubrizgavanje konstruktora) za ubrizgavanje instance klase LogWrapper kako je prikazano u donjem popisu kodova.

javna klasa ProductBL

    {

        samo za čitanje IWrapper _wrapper;

        statički niz _poruka = ​​null;

        javni ProductBL (omot IWrapper)

        {

            _motač = omot;

        }

        javna void LogMessage (niz poruka)

        {

            _poruka = ​​poruka;

            _wrapper.LogData (_poruka);

        }

    }

Metoda LogMessage klase ProductBL poziva metodu LogData na instanci klase LogWrapper koja je prethodno ubrizgana.

Upotrijebite xUnit i Moq za izradu jedinične metode ispitivanja u C #

Otvorite datoteku UnitTest1.cs i preimenujte klasu UnitTest1 u UnitTestForStaticMethodsDemo. Datoteke UnitTest1.cs automatski će se preimenovati u UnitTestForStaticMethodsDemo.cs. Sada ćemo iskoristiti Moq okvir za postavljanje, testiranje i provjeru lažnih podataka.

Sljedeći isječak koda ilustrira kako možete koristiti Moq framework za jedinstvene metode ispitivanja u C #.

var mock = novi Mock ();

mock.Setup (x => x.LogData (It.IsAny ()));

novi ProductBL (mock.Object) .LogMessage ("Hello World!");

mock.VerifyAll ();

Kada izvršite test, evo kako bi izlaz trebao izgledati u prozoru Test Explorer.

Cjelovit popis kodova klase testa dat je u nastavku za vašu referencu.

javna klasa UnitTestForStaticMethodsDemo

    {

        [Činjenica]

        javna praznina StaticMethodTest ()

        {

            var mock = novi Mock ();

            mock.Setup (x => x.LogData (It.IsAny ()));

            novi ProductBL (mock.Object) .LogMessage ("Hello World!");

            mock.VerifyAll ();

        }

    }

Jedinstveno testiranje postupak je kojim se testiraju jedinice koda u aplikaciji kako bi se provjerilo podudaraju li se stvarni rezultati vašeg jediničnog testa sa željenim rezultatima. Ako se razumno koristi, jedinstveno testiranje može pomoći u sprečavanju bugova u fazi razvoja projekta.

Statičke metode mogu predstavljati brojne probleme kada ih pokušate jedinica testirati koristeći imitacije. Ako vaša aplikacija zahtijeva ruganje statičkoj metodi, trebali biste uzeti u obzir da dizajn miriše - tj. Pokazatelj lošeg dizajna. U sljedećem ću članku ovdje detaljnije raspraviti o lažnim i lažnim podacima.

Kako učiniti više u C #:

  • Kako refaktorirati Božje objekte u C #
  • Kako koristiti ValueTask u C #
  • Kako se koristi nepromjenjivost u C
  • Kako koristiti const, readonly i static u C #
  • Kako koristiti bilješke podataka u C #
  • Kako raditi s GUID-ovima u C # 8
  • Kada koristiti apstraktnu klasu naspram sučelja u C #
  • Kako raditi s AutoMapperom u C #
  • Kako koristiti lambda izraze u C #
  • Kako raditi s delegatima Action, Func i Predicate u C #
  • Kako raditi s delegatima u C #
  • Kako implementirati jednostavni zapisnik u C #
  • Kako raditi s atributima u C #
  • Kako raditi s log4netom na C #
  • Kako implementirati obrazac dizajna spremišta u C #
  • Kako raditi s refleksijom u C #
  • Kako raditi s nadzornikom datoteka u C #
  • Kako izvesti lijenu inicijalizaciju u C #
  • Kako raditi s MSMQ-om u C #
  • Kako raditi s metodama produženja u C #
  • Kako do nas lambda izrazi u C #
  • Kada upotrijebiti hlapljivu ključnu riječ u C #
  • Kako koristiti ključnu riječ yield u C #
  • Kako implementirati polimorfizam u C #
  • Kako izraditi vlastiti planer zadataka u C #
  • Kako raditi s RabbitMQ u C #
  • Kako raditi s korpicom u C #
  • Istraživanje virtualnih i apstraktnih metoda u C #
  • Kako koristiti Dapper ORM u C #
  • Kako koristiti uzorak dizajna muhe u C #