Cvičení – test jednotek funkce Azure Functions

Dokončeno

Testování jednotek je základní součástí agilní metodologie. V sadě Visual Studio je k dispozici šablona projektu testů. Pomocí této šablony vytvoříte testy jednotek pro aplikace a stejný postup můžete použít k testování Azure Functions.

Ve scénáři online webu luxusních hodinek má váš vývojový tým zásady pro dosažení alespoň 80% pokrytí kódu při testování jednotek. Chcete implementovat stejné zásady pro Azure Functions.

Tady se dozvíte, jak pomocí xUnit testovací architektury se sadou Visual Studio otestovat Azure Functions.

Vytvoření projektu testů jednotek

Prvním krokem je vytvoření projektu, který obsahuje testy jednotek, a jeho přidání do řešení, které obsahuje vaši aplikaci Funkcí Azure. Pomocí následujících kroků můžete vytvořit projekt testů jednotek pro testování funkce WatchInfo.

  1. V sadě Visual Studio v okně Průzkumníka řešení klikněte pravým tlačítkem na řešení WatchPortalFunction, vyberte Přidat a potom zvolte Nový projekt.

    Snímek obrazovky Průzkumníka řešení zobrazující příkaz pro přidání nového projektu do řešení

  2. V okně Přidat nový projekt se posuňte dolů, vyberte šablonu ikony xUnit Test ProjectC#+ a pak vyberte Další.

    Snímek obrazovky s oknem Přidat nový projekt Je vybrána šablona projektu testování xUnit.

  3. Objeví se okno Konfigurovat nový projekt. Do pole Název projektu zadejte WatchFunctionsTests. Vedle pole Umístění vyberte ikonu pro procházení a pak vyberte složku WatchPortalFunction.

  4. Vyberte Další. Zobrazí se okno Další informace .

  5. V části Cílová architektura. přijměte výchozí hodnotu rozhraní .NET 6.0 (dlouhodobá podpora).

  6. Vyberte Vytvořit.

  7. Po přidání projektu klikněte pravým tlačítkem myši na projekt WatchFunctionTests v okně Průzkumník řešení a pak vyberte Spravovat balíčky NuGet.

  8. V okně NuGet: WatchFunctionTests vyberte kartu Procházet. Do vyhledávacíhopole zadejte Microsoft.AspNetCore.Mvc. Vyberte balíček Microsoft.AspNetCore.Mvc a pak zvolte Nainstalovat.

    Snímek obrazovky s oknem Správce balíčků NuGet Uživatel instaluje balíček Microsoft.AspNetCore.Mvc.

    Poznámka:

    Projekt testů vytvoří napodobeninu prostředí HTTP. Třídy, které jsou k tomu třeba, jsou v balíčku Microsoft.AspNetCore.Mvc.

  9. Počkejte, než se balíček nainstaluje. Pokud se zobrazí okno se zprávou Náhled změn, vyberte OK. V okně se zprávou Souhlas s podmínkami licence zvolte Přijmout.

  10. Po přidání balíčku klikněte v okně Průzkumník řešení v projektu WatchFunctionsTests pravým tlačítkem myši na soubor UnitTest1.cs a pak vyberte Přejmenovat. Změňte název souboru na WatchFunctionUnitTests.cs. V okně se zprávou, které se zobrazí, vyberte Ano, abyste přejmenovali všechny odkazy UnitTest1 na WatchFunctionUnitTests.

  11. V okně Průzkumník řešení klikněte v projektu WatchFunctionsTests pravým tlačítkem myši na Závislosti a pak vyberte Přidat odkaz na projekt.

  12. V okně Správce odkazů vyberte projekt WatchPortalFunction a pak zvolte OK.

Přidání testů jednotek pro funkci WatchInfo

Teď můžete přidat testy jednotek do projektu testů. Ve scénáři prodeje luxusních hodinek chcete zajistit, aby funkce WatchInfo vždy vrátila odpověď OK, když je v řetězci dotazu požadavku uveden model, a odpověď Bad (Chyba), když je řetězec dotazu prázdný nebo neobsahuje parametr model.

Chcete-li toto chování ověřit, přidáte do watchFunctionsTests dvojici testů faktů.

  1. Pokud chcete v okně Průzkumník řešení zobrazit WatchPortalFunction v okně kódu, poklikejte na soubor WatchFunctionUnitTests.cs.

  2. Do seznamu na začátku souboru přidejte následující direktivy using.

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Microsoft.Extensions.Logging.Abstractions;
    
  3. Změňte název metody Test1 na TestWatchFunctionSuccess.

  4. V těle metody TestWatchFunctionSuccess přidejte následující kód. Tento příkaz vytvoří napodobeninu kontextu HTTP a požadavek HTTP. Součástí tohoto požadavku je řetězec dotazu, který obsahuje parametr model nastavený na abc.

    var queryStringValue = "abc";
    var request = new DefaultHttpRequest(new DefaultHttpContext())
    {
        Query = new QueryCollection
        (
            new System.Collections.Generic.Dictionary<string, StringValues>()
            {
                { "model", queryStringValue }
            }
        )
    };
    
  5. Do metody přidejte následující příkaz. Tento příkaz vytvoří fiktivní protokolovač.

    var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
  6. Do metody přidejte následující kód. Tyto příkazy vyvolají funkci WatchInfo a předají fiktivní požadavek a protokolovač jako parametry.

    var response = WatchPortalFunction.WatchInfo.Run(request, logger);
    response.Wait();
    
  7. Do metody přidejte následující kód. Tento kód zkontroluje správnost odpovědi funkce. V tomto případě by funkce měla vrátit odpověď OK obsahující očekávaná data v těle.

    // Check that the response is an "OK" response
    Assert.IsAssignableFrom<OkObjectResult>(response.Result);
    
    // Check that the contents of the response are the expected contents
    var result = (OkObjectResult)response.Result;
    dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 };
    string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}";
    Assert.Equal(watchInfo, result.Value);
    

    Úplná metoda by měla vypadat takto.

    [Fact]
    public void TestWatchFunctionSuccess()
    {
        var queryStringValue = "abc";
        var request = new DefaultHttpRequest(new DefaultHttpContext())
        {
            Query = new QueryCollection
            (
                new System.Collections.Generic.Dictionary<string, StringValues>()
                {
                    { "model", queryStringValue }
                }
            )
        };
    
        var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
        var response = WatchPortalFunction.WatchInfo.Run(request, logger);
        response.Wait();
    
        // Check that the response is an "OK" response
        Assert.IsAssignableFrom<OkObjectResult>(response.Result);
    
        // Check that the contents of the response are the expected contents
        var result = (OkObjectResult)response.Result;
        dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 };
        string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}";
        Assert.Equal(watchInfo, result.Value);
    }
    
  8. Přidejte další dvě metody nazvané TestWatchFunctionFailureNoQueryString a TestWatchFunctionFailureNoModel. Metoda TestWatchFunctionFailureNoQueryString ověřuje, jestli funkce WatchInfo selže bez výpadku, pokud není zadán řetězec dotazu. Metoda TestWatchFunctionFailureNoModel vyhledává stejnou chybu, pokud je do této funkce předán řetězec dotazu, který neobsahuje parametr modelu.

    [Fact]
    public void TestWatchFunctionFailureNoQueryString()
    {
        var request = new DefaultHttpRequest(new DefaultHttpContext());
        var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
        var response = WatchPortalFunction.WatchInfo.Run(request, logger);
        response.Wait();
    
        // Check that the response is an "Bad" response
        Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result);
    
        // Check that the contents of the response are the expected contents
        var result = (BadRequestObjectResult)response.Result;
        Assert.Equal("Please provide a watch model in the query string", result.Value);
    }
    
    [Fact]
    public void TestWatchFunctionFailureNoModel()
    {
        var queryStringValue = "abc";
        var request = new DefaultHttpRequest(new DefaultHttpContext())
        {
            Query = new QueryCollection
            (
                new System.Collections.Generic.Dictionary<string, StringValues>()
                {
                    { "not-model", queryStringValue }
                }
            )
        };
    
        var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
        var response = WatchPortalFunction.WatchInfo.Run(request, logger);
        response.Wait();
    
        // Check that the response is an "Bad" response
        Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result);
    
        // Check that the contents of the response are the expected contents
        var result = (BadRequestObjectResult)response.Result;
        Assert.Equal("Please provide a watch model in the query string", result.Value);
    }
    

Spuštění testů

  1. V horním řádku nabídek v části Test vyberte Spustit všechny testy.

    Snímek obrazovky s nabídkou Test v sadě Visual Studio Uživatel vybral možnost Spustit –> všechny testy.

  2. V okně Průzkumníka testů by se měly úspěšně dokončit všechny tři testy.

    Snímek obrazovky s oknem Team Explorer Všechny tři testy byly úspěšně spuštěny.

  3. V okně Průzkumníka řešení poklikejte v projektu WatchPortalFunction na WatchInfo.cs, abyste tento soubor zobrazili v editoru kódu.

  4. Vyhledejte následující kód.

    // Retrieve the model id from the query string
    string model = req.Query["model"];
    
  5. Změňte příkaz, který nastavuje proměnnou model, následujícím způsobem. Tato změna simuluje, aby vývojář udělal chybu v kódu.

    string model = req.Query["modelll"];
    
  6. V horním řádku nabídek v části Test vyberte Spustit všechny testy. Tentokrát by test TestWatchFunctionSuccess měl být neúspěšný. K této chybě dochází, protože funkce WatchInfo nenajde parametr pojmenovaný modelll v řetězci dotazu, takže funkce vrátí chybnou odpověď.

    Snímek obrazovky s oknem Team Explorer Test TestWatchFunctionSuccess selhal.

V této lekci jste viděli, jak vytvořit projekt testování jednotek a implementovat testy jednotek pro funkci Azure Functions.