Dela via


Testa Razor komponenter i ASP.NET Core Blazor

Not

Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Av Egil Hansen

Att testa Razor komponenter är en viktig aspekt av att släppa stabila och underhållsbara Blazor appar.

För att testa en Razor-komponent är komponenten under test (CUT):

  • Renderas med relevanta indata för testet.
  • Beroende på vilken typ av test som utförs, eventuellt beroende på interaktion eller ändring. Händelsehanterare kan till exempel utlösas, till exempel en onclick händelse för en knapp.
  • Inspekterad med avseende på förväntade värden. Ett test godkänns när ett eller flera inspekterade värden matchar de förväntade värdena för testet.

Testmetoder

Två vanliga metoder för att testa Razor komponenter är testning från slutpunkt till slutpunkt (E2E) och enhetstestning:

  • Enhetstestning: Enhetstester skrivs med ett enhetstestbibliotek som tillhandahåller:

    • Komponentrendering.
    • Kontroll av komponentens utdata och tillstånd.
    • Aktivering av händelsehanterare och livscykelmetoder.
    • Försäkran om att komponentbeteendet är korrekt.

    bUnit är ett exempel på ett bibliotek som möjliggör Razor komponentenhetstestning.

  • E2E-testning: En testkörare kör en Blazor app som innehåller CUT och automatiserar en webbläsarinstans. Testverktyget inspekterar och interagerar med CUT via webbläsaren. Playwright för .NET är ett exempel på ett E2E-testramverk som kan användas med Blazor appar.

I enhetstestning ingår endast komponenten Razor (Razor/C#). Externa beroenden, till exempel tjänster och JS interop, måste hånas. I E2E-testning ingår Razor-komponenten och all dess extra infrastruktur i testet, inklusive CSS, JSoch DOM- och webbläsar-API:er.

Testomfång beskriver hur omfattande testerna är. Testomfånget påverkar vanligtvis testernas hastighet. Enhetstester körs på en delmängd av appens undersystem och körs vanligtvis i millisekunder. E2E-tester, som testar en bred grupp av appens undersystem, kan ta flera sekunder att slutföra.

Enhetstestning ger också åtkomst till instansen av CUT, vilket möjliggör inspektion och verifiering av komponentens interna tillstånd. Detta är normalt inte möjligt i E2E-testning.

När det gäller komponentens miljö måste E2E-tester se till att det förväntade miljötillståndet har uppnåtts innan verifieringen påbörjas. Annars är resultatet oförutsägbart. Vid enhetstestning är återgivningen av CUT och testets livscykel mer integrerad, vilket förbättrar teststabiliteten.

E2E-testning innebär att starta flera processer, nätverks- och disk-I/O och annan undersystemaktivitet som ofta leder till dålig testtillförlitlighet. Enhetstester är vanligtvis isolerade från den här typen av problem.

I följande tabell sammanfattas skillnaden mellan de två testmetoderna.

Förmåga Enhetstestning E2E-testning
Testomfång Endast Razor-komponent (Razor/C#) Razor komponent (Razor/C#) med CSS/JS
Testkörningstid Millisekunder Sekunder
Åtkomst till komponentinstansen Ja Nej
Känslig för miljön Nej Ja
Tillförlitlighet Mer tillförlitlig Mindre tillförlitlig

Välj den lämpligaste testmetoden

Tänk på scenariot när du väljer vilken typ av testning som ska utföras. Vissa överväganden beskrivs i följande tabell.

Scenario Föreslagen metod Anmärkningar
Komponent utan JS interoplogik Enhetstestning När det inte finns något beroende av JS interop i en Razor komponent kan komponenten testas utan åtkomst till JS eller DOM-API:et. I det här scenariot finns det inga nackdelar med att välja enhetstestning.
Komponent med enkel JS interoplogik Enhetstestning Det är vanligt att komponenter frågar DOM eller utlöser animeringar via JS interop. Enhetstestning föredras vanligtvis i det här scenariot, eftersom det är enkelt att mocka JS-interaktion genom IJSRuntime-gränssnittet.
Komponent som är beroende av komplex JS kod Enhetstestning och separat JS testning Om en komponent använder JS interop för att anropa ett stort eller komplext JS bibliotek, men interaktionen mellan Razor komponenten och JS-biblioteket är enkel, är den bästa metoden sannolikt att behandla komponenten och JS-biblioteket eller koden som två separata delar och testa var och en individuellt. Testa Razor komponenten med ett enhetstestbibliotek och testa JS med ett JS testbibliotek.
Komponent med logik som är beroende av JS manipulering av webbläsarens DOM E2E-testning När en komponents funktioner är beroende av JS och dess manipulering av DOM kontrollerar du både JS och Blazor kod tillsammans i ett E2E-test. Det här är den metod som Blazor-ramverksutvecklarna har använt med Blazor:s webbläsarrenderingslogik, som har närekopplade C#- och JS-kod. Koden C# och JS måste fungera tillsammans för att återge Razor komponenter i en webbläsare korrekt.
Komponent som är beroende av ett klassbibliotek från tredje part med beroenden som är svåra att simulera. E2E-testning När en komponents funktionalitet är beroende av ett klassbibliotek från tredje part som har beroenden som är svåra att simulera, till exempel JS interop, kan E2E-testning vara det enda alternativet för att testa komponenten.

Testa komponenter med bUnit

Det finns inget officiellt Microsoft-testramverk för Blazor, men det communitydrivna projektet bUnit ger ett bekvämt sätt att enhetstesta Razor komponenter.

Not

bUnit är ett testbibliotek från tredje part och stöds inte eller underhålls inte av Microsoft.

bUnit fungerar med allmänna testramverk, till exempel MSTest, NUnitoch xUnit. Dessa testramverk gör att bUnit-tester ser ut och känns som vanliga enhetstester. bUnit-tester som är integrerade med ett allmänt testramverk körs vanligtvis med:

Notera

Testbegrepp och testimplementeringar i olika testramverk är liknande men inte identiska. Se testramverkets dokumentation för vägledning.

Följande visar strukturen för ett bUnit-test på den Counter komponenten i en app baserat på en Blazor projektmall. Komponenten Counter visar och ökar en räknare baserat på att användaren väljer en knapp på sidan:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Följande bUnit-test verifierar att CUT-räknaren ökar korrekt när knappen är markerad:

@code {
    [Fact]
    public void CounterShouldIncrementWhenClicked()
    {
        // Arrange
        using var ctx = new TestContext();
        var cut = ctx.Render(@<Counter />);
        var paraElm = cut.Find("p");

        // Act
        cut.Find("button").Click();

        // Assert
        var paraElmText = paraElm.TextContent;
        paraElm.MarkupMatches("Current count: 1");
    }
}

Tester kan också skrivas i en C#-klassfil:

public class CounterTests
{
    [Fact]
    public void CounterShouldIncrementWhenClicked()
    {
        // Arrange
        using var ctx = new TestContext();
        var cut = ctx.RenderComponent<Counter>();
        var paraElm = cut.Find("p");

        // Act
        cut.Find("button").Click();

        // Assert
        var paraElmText = paraElm.TextContent;
        paraElmText.MarkupMatches("Current count: 1");
    }
}

Följande åtgärder utförs i varje steg i testet:

  • Ordna: Komponenten Counter återges med bUnits TestContext. CUT:s styckeelement (<p>) hittas och tilldelas till paraElm. I Razor syntax kan en komponent skickas som en RenderFragment till bUnit.

  • Act: Knappens element (<button>) lokaliseras och väljs genom att anropa Click, vilket bör öka räknaren och uppdatera innehållet i stycketaggen (<p>). Textinnehållet för styckeelement hämtas genom att anropa TextContent.

  • Assert: MarkupMatches anropas på textinnehållet för att kontrollera att det matchar den förväntade strängen, som är Current count: 1.

Not

Metoden MarkupMatches assert skiljer sig från en vanlig strängjämförelse (till exempel Assert.Equal("Current count: 1", paraElmText);). MarkupMatches utför en semantisk jämförelse av indata och förväntad HTML-kod. En semantisk jämförelse är medveten om HTML-semantik, vilket innebär att saker som obetydliga blanksteg ignoreras. Detta resulterar i stabilare tester. Mer information finns i Anpassa den semantiska HTML-jämförelsen.

Ytterligare resurser