Programmering

Sådan enhedstest statiske metoder i C #

Når du bygger eller arbejder i .NET-applikationer, bruger du ofte statiske metoder. Metoder i C # kan være enten statiske eller ikke-statiske. En ikke-statisk metode (også kendt som en instansmetode) kan påberåbes på en forekomst af den klasse, den tilhører. Statiske metoder behøver ikke, at en forekomst af klassen påberåbes - de kan kaldes på klassen selv.

Selvom testning af en ikke-statisk metode (i det mindste en, der ikke kalder en statisk metode eller interagerer med eksterne afhængigheder) er ligetil, er det ikke let at teste en statisk metode. Denne artikel taler om, hvordan du kan overvinde denne udfordring og teste statiske metoder i C #.

[Også om: Sådan refaktorerer Gud objekter i C #]

For at arbejde med kodeeksemplerne i denne artikel skal du have Visual Studio 2019 installeret i dit system. Hvis du ikke allerede har en kopi, kan du downloade Visual Studio 2019 her.

Opret et .NET Core-konsolapplikationsprojekt i Visual Studio

Lad os først oprette et .NET Core Console Application-projekt i Visual Studio. Forudsat at Visual Studio 2019 er installeret i dit system, skal du følge nedenstående trin for at oprette et nyt .NET Core-konsolapplikationsprojekt i Visual Studio.

  1. Start Visual Studio IDE.
  2. Klik på "Opret nyt projekt."
  3. I vinduet "Opret nyt projekt" skal du vælge "Konsolapp (.NET Core)" fra listen over skabeloner, der vises.
  4. Klik på Næste.
  5. I vinduet "Konfigurer dit nye projekt", der vises nedenfor, skal du angive navnet og placeringen for det nye projekt.
  6. Klik på Opret.

Dette vil skabe et nyt .NET Core-konsolapplikationsprojekt i Visual Studio 2019. På lignende måde skal du oprette yderligere to projekter - et klassebibliotek og et enhedstestprojekt (xUnit test) -projekt. Vi bruger disse tre projekter til at illustrere enhedstest af statiske metoder i de efterfølgende afsnit i denne artikel.

Når en statisk metode kan og ikke kan testes enhed

Enhedstest af en statisk metode er ikke anderledes end enhedstest af en ikke-statisk metode. Statiske metoder er ikke uprøvelige i sig selv. En statisk metode, der ikke har nogen tilstand eller ikke ændrer tilstand, kan testes enhed. Så længe metoden og dens afhængigheder er idempotent, kan metoden testes enhed. Problemer opstår, når den statiske metode kalder andre metoder, eller når det objekt, der testes, kalder den statiske metode. På den anden side, hvis objektet, der testes, kalder en instansmetode, kan du enkelt teste det let.

En statisk metode kan ikke enhedstestes, hvis noget af det følgende gælder:

  • Den statiske metode interagerer med eksterne afhængigheder såsom en database, filsystem, netværk eller ekstern API.
  • Den statiske metode indeholder tilstandsinformation, dvs. hvis den cachelagrer data i et statisk objekt i klassen.

Overvej følgende kodestykke, der viser to klasser, nemlig ProductBL og Logger. Mens ProductBL er en ikke-statisk klasse, er Logger en statisk klasse. Bemærk, at skrivemetoden i Logger-klassen er kaldet fra LogMessage-metoden i ProductBL-klassen.

offentlig klasse ProductBL

    {

offentlig ugyldig LogMessage (streng besked)

        {

Logger.Write (besked);

        }

    }

offentlig klasse Logger

    {

offentlig statisk ugyldighed Skriv (streng besked)

        {

// Skriv din kode her for at logge data

        }

    }

Antag, at skrivemetoden i Logger-klassen opretter forbindelse til en database og derefter skriver dataene til en databasetabel. Navnet på databasen og dens tabel, hvor dataene skal skrives, kan være forudkonfigureret i filen appsettings.json. Hvordan kan du nu skrive enhedstest til ProductBL-metoden?

Bemærk, at statiske metoder ikke let kan spottes. Hvis du f.eks. Har to klasser med navnet A og B, og klasse A bruger et statisk medlem af klasse B, ville du ikke være i stand til at isolere testklasse A.

Tre måder at enhedsteste statiske metoder på

Du kan bruge Moq til at spotte ikke-statiske metoder, men det kan ikke bruges til at spotte statiske metoder. Selvom statiske metoder ikke kan spottes let, er der et par måder at spotte statiske metoder på.

Du kan drage fordel af Moles eller Fakes-rammen fra Microsoft til at spotte statiske metodeopkald. (Fakes-rammen blev inkluderet i Visual Studio 2012 som efterfølgeren til Moles - det er den næste generation af Moles og Stubs.) En anden måde at spotte statisk metodeopkald er ved hjælp af delegerede. Der er endnu en måde at spotte statiske metodeopkald på i et program - ved hjælp af indpakningsklasser og afhængighedsinjektion.

IMHO denne sidste mulighed er den bedste løsning på problemet. Alt hvad du skal gøre er at pakke det statiske metodeopkald ind i en instansmetode og derefter bruge afhængighedsinjektion til at injicere en forekomst af indpakningsklassen til den klasse, der testes.

Opret en indpakningsklasse i C #

Følgende kodestykke illustrerer LogWrapper-klassen, der implementerer IWrapper-grænsefladen og indpakker et opkald til Logger.Write () -metoden i en instansmetode kaldet LogData.

offentlig klasse LogWrapper: IWrapper

    {

streng _besked = null;

offentlig LogWrapper (streng besked)

        {

_message = besked;

        }

offentlig ugyldig LogData (streng besked)

        {

_ besked = besked;

Logger.Write (_meddelelse);

        }

    }

Følgende kodestykke viser IWrapper-grænsefladen. Den indeholder erklæringen om LogData-metoden.

offentlig grænseflade IWrapper

    {

ugyldige LogData (streng besked);

    }

ProduktBL-klassen bruger afhængighedsinjektion (konstruktionsinjektion) til at injicere en forekomst af LogWrapper-klassen som vist i kodelisten nedenfor.

offentlig klasse ProductBL

    {

readonly IWrapper _wrapper;

statisk streng _message = null;

offentlig ProductBL (IWrapper indpakning)

        {

_indpakning = indpakning;

        }

offentlig ugyldig LogMessage (streng besked)

        {

_ besked = besked;

_wrapper.LogData (_meddelelse);

        }

    }

LogMessage-metoden i ProductBL-klassen kalder LogData-metoden på den forekomst af LogWrapper-klassen, der er blevet injiceret tidligere.

Brug xUnit og Moq til at oprette en enhedstestmetode i C #

Åbn filen UnitTest1.cs, og omdøb UnitTest1-klassen til UnitTestForStaticMethodsDemo. UnitTest1.cs-filerne omdøbes automatisk til UnitTestForStaticMethodsDemo.cs. Vi udnytter nu Moq-rammen til at oprette, teste og verificere mocks.

Følgende kodestykke illustrerer, hvordan du kan bruge Moq-rammen til at måle testmetoder i C #.

var mock = ny Mock ();

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

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

mock.VerifyAll ();

Når du udfører testen, skal du se, hvordan output skal se ud i Test Explorer-vinduet.

Den komplette kodeliste over testklassen er angivet nedenfor til din reference.

offentlig klasse UnitTestForStaticMethodsDemo

    {

[Faktum]

offentlig ugyldighed StaticMethodTest ()

        {

var mock = ny Mock ();

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

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

mock.VerifyAll ();

        }

    }

Enhedstest er en proces, der tester enheder af kode i en applikation for at kontrollere, om de faktiske resultater fra din enhedstest svarer til de ønskede resultater. Hvis det bruges med omhu, kan enhedstest hjælpe med at forhindre bugs i udviklingsfasen af ​​et projekt.

Statiske metoder kan udgøre en række problemer, når du prøver at enhedstest dem ved hjælp af mocks. Hvis din applikation kræver, at du spotter en statisk metode, skal du overveje, at en designluft - dvs. en indikator for et dårligt design. Jeg vil diskutere mocks, forfalskninger og stubbe mere detaljeret i en fremtidig artikel her.

Sådan gør du mere i C #:

  • Sådan refaktorerer du Guds objekter i C #
  • Sådan bruges ValueTask i C #
  • Sådan bruges uforanderlighed i C
  • Sådan bruges const, readonly og static i C #
  • Sådan bruges datanoteringer i C #
  • Sådan arbejder du med GUID'er i C # 8
  • Hvornår skal man bruge en abstrakt klasse vs. interface i C #
  • Sådan arbejder du med AutoMapper i C #
  • Sådan bruges lambda-udtryk i C #
  • Sådan arbejder du med Action-, Func- og Predicate-delegerede i C #
  • Sådan arbejder du med delegerede i C #
  • Sådan implementeres en simpel logger i C #
  • Sådan arbejder du med attributter i C #
  • Sådan arbejder du med log4net i C #
  • Sådan implementeres depotdesignmønsteret i C #
  • Sådan arbejder du med refleksion i C #
  • Sådan arbejder du med filsystemwatcher i C #
  • Sådan udføres doven initialisering i C #
  • Sådan arbejder du med MSMQ i C #
  • Sådan arbejder du med udvidelsesmetoder i C #
  • Hvordan vi lambda-udtryk i C #
  • Hvornår skal du bruge det flygtige nøgleord i C #
  • Sådan bruges afkastnøgleordet i C #
  • Sådan implementeres polymorfisme i C #
  • Sådan bygger du din egen opgaveplanlægning i C #
  • Sådan arbejder du med RabbitMQ i C #
  • Sådan arbejder du med en tuple i C #
  • Udforskning af virtuelle og abstrakte metoder i C #
  • Sådan bruges Dapper ORM i C #
  • Sådan bruges designmønsteret med flyvægt i C #
$config[zx-auto] not found$config[zx-overlay] not found