Ćwiczenie — test jednostkowy funkcji platformy Azure

Ukończone

Testowanie jednostek to podstawowy element metodologii Agile. W programie Visual Studio jest dostępny szablon projektu testowego. Za pomocą tego szablonu można tworzyć testy jednostkowe na potrzeby swoich aplikacji — a tę samą technikę możesz zastosować do testowania funkcji usługi Azure Functions.

W scenariuszu witryny internetowej luksusowych zegarków twój zespół programistyczny ma zasady osiągnięcia co najmniej 80% pokrycia kodu w testach jednostkowych. Chcesz zastosować tę samą zasadę w przypadku funkcji usługi Azure Functions.

W tym miejscu zobaczysz, jak używać platformy testowej xUnit z programem Visual Studio do testowania usługi Azure Functions.

Tworzenie projektu testów jednostkowych

Pierwszym krokiem jest utworzenie projektu zawierającego testy jednostkowe i dodanie go do rozwiązania zawierającego aplikację funkcji platformy Azure. Skorzystaj z poniższych instrukcji, aby utworzyć projekt testów jednostkowych do testowania funkcji WatchInfo.

  1. W programie Visual Studio w oknie Eksplorator rozwiązań kliknij prawym przyciskiem myszy rozwiązanie WatchPortalFunction, wybierz przycisk Dodaj, a następnie wybierz pozycję Nowy projekt.

    Zrzut ekranu Eksploratora rozwiązań z widocznym poleceniem dodawania nowego projektu do rozwiązania.

  2. W oknie Dodawanie nowego projektu przewiń w dół, wybierz szablon ikony XUnit Test Project C#+, a następnie wybierz przycisk Dalej.

    Zrzut ekranu przedstawiający okno Dodawanie nowego projektu. Wybrano szablon projektu testowego xUnit.

  3. Zostanie wyświetlone okno Konfiguruj nowy projekt. W polu Nazwa projektu wprowadź WatchFunctionsTests. Obok pola Lokalizacja wybierz ikonę przeglądania, a następnie wybierz folder WatchPortalFunction.

  4. Wybierz Dalej. Zostanie wyświetlone okno Dodatkowe informacje .

  5. W obszarze Platforma docelowa. Zaakceptuj wartość domyślną platformy .NET 6.0 (obsługa długoterminowa).

  6. Wybierz pozycję Utwórz.

  7. Po dodaniu projektu kliknij prawym przyciskiem myszy projekt WatchFunctionTests w oknie Eksplorator rozwiązań, a następnie wybierz polecenie Zarządzaj pakietami NuGet.

  8. W oknie NuGet: WatchFunctionTests wybierz kartę Przeglądaj. W polu Wyszukiwania wprowadź wartość Microsoft.AspNetCore.Mvc. Wybierz pakiet Microsoft.AspNetCore.Mvs, a następnie wybierz przycisk Zainstaluj.

    Zrzut ekranu przedstawiający okno Menedżer pakietów NuGet. Użytkownik instaluje pakiet Microsoft.AspNetCore.Mvc.

    Uwaga

    W projekcie testowym zostanie utworzone pozorne środowisko HTTP. Pakiet Microsoft.AspNetCore.Mvc zawiera klasy wymagane do tego celu.

  9. Zaczekaj na zainstalowanie pakietu. Jeśli zostanie wyświetlone okno komunikatu Podgląd zmian, wybierz przycisk OK. W oknie komunikatu Akceptacja licencji wybierz pozycję Akceptuję.

  10. Po dodaniu pakietu w oknie Eksplorator rozwiązań w projekcie WatchFunctionsTests kliknij prawym przyciskiem myszy plik UnitTest1.cs, a następnie wybierz polecenie Zmień nazwę. Zmień nazwę pliku na WatchFunctionUnitTests.cs. Aby zamienić wszystkie odwołania do nazwy UnitTest1 na odwołania do nazwy WatchFunctionUnitTests, w wyświetlonym oknie komunikatu wybierz pozycję Tak.

  11. W oknie Eksplorator rozwiązań w projekcie WatchFunctionsTests kliknij prawym przyciskiem myszy pozycję Zależności, a następnie wybierz polecenie Dodaj odwołanie do projektu.

  12. W oknie Menedżer odwołań wybierz projekt WatchPortalFunction, a następnie wybierz przycisk OK.

Dodawanie testów jednostkowych dla funkcji WatchInfo

Możesz teraz dodać testy jednostkowe do projektu testowego. W scenariuszu dotyczącym luksusowych zegarków chcesz, aby funkcja WatchInfo zawsze zwracała odpowiedź OK, jeśli w ciągu zapytania w żądaniu podano model, a odpowiedź Bad, jeśli ciąg zapytania jest pusty lub nie zawiera parametru model.

Aby zweryfikować to zachowanie, należy dodać parę testów faktów do funkcji WatchFunctionsTests.

  1. W oknie Eksplorator rozwiązań, aby wyświetlić element WatchPortalFunction w oknie kodu, kliknij dwukrotnie plik WatchFunctionUnitTests.cs.

  2. Na początku pliku dodaj do listy następujące dyrektywy using.

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Microsoft.Extensions.Logging.Abstractions;
    
  3. Zmień nazwę metody Test1 na TestWatchFunctionSuccess.

  4. W treści metody TestWatchFunctionSuccess dodaj następujący kod. Ta instrukcja tworzy pozorny kontekst HTTP i żądanie HTTP. Żądanie zawiera ciąg zapytania z parametrem model, ustawionym na wartość abc.

    var queryStringValue = "abc";
    var request = new DefaultHttpRequest(new DefaultHttpContext())
    {
        Query = new QueryCollection
        (
            new System.Collections.Generic.Dictionary<string, StringValues>()
            {
                { "model", queryStringValue }
            }
        )
    };
    
  5. Dodaj następującą instrukcję do metody. Ta instrukcja tworzy fikcyjny rejestrator.

    var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
    
  6. Dodaj do metody następujący kod. Te instrukcje wywołują funkcję WatchInfo, przekazując fikcyjne żądanie i fikcyjny rejestrator jako parametry.

    var response = WatchPortalFunction.WatchInfo.Run(request, logger);
    response.Wait();
    
  7. Dodaj do metody następujący kod. Ten kod sprawdza, czy odpowiedź z funkcji jest poprawna. W takim przypadku funkcja powinna zwrócić odpowiedź OK zawierającą oczekiwane dane w treści.

    // 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);
    

    Kompletna metoda powinna wyglądać podobnie do poniższej.

    [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. Dodaj dwie kolejne metody o nazwach TestWatchFunctionFailureNoQueryString i TestWatchFunctionFailureNoModel. Funkcja TestWatchFunctionFailureNoQueryString umożliwia sprawdzenie, czy funkcja WatchInfo bezpiecznie kończy się niepowodzeniem w przypadku niewprowadzenia ciągu zapytania. Funkcja TestWatchFunctionFailureNoModel sprawdza to samo działanie, gdy wprowadzony ciąg zapytania nie zawiera parametru 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);
    }
    

Uruchamianie testów

  1. Na górnym pasku menu w obszarze Test wybierz pozycję Uruchom wszystkie testy.

    Zrzut ekranu przedstawiający menu Test w programie Visual Studio. Użytkownik wybrał pozycję Uruchom —> wszystkie testy.

  2. W oknie Eksplorator testów wszystkie trzy testy powinny zakończyć się pomyślnie.

    Zrzut ekranu przedstawiający okno Programu Team Explorer. Wszystkie trzy testy zostały pomyślnie uruchomione.

  3. W oknie Eksplorator rozwiązań w projekcie WatchPortalFunction kliknij dwukrotnie plik WatchInfo.cs, aby wyświetlić go w edytorze kodu.

  4. Znajdź następujący kod.

    // Retrieve the model id from the query string
    string model = req.Query["model"];
    
  5. Zmień instrukcję ustawiającą zmienną model w następujący sposób. Ta zmiana symuluje, że deweloper popełnia błąd w kodzie.

    string model = req.Query["modelll"];
    
  6. Na górnym pasku menu w obszarze Test wybierz pozycję Uruchom wszystkie testy. Tym razem test TestWatchFunctionSuccess powinien zakończyć się niepowodzeniem. Ten błąd występuje, ponieważ funkcja WatchInfo nie znajduje parametru o nazwie modelll w ciągu zapytania, dlatego funkcja zwraca nieprawidłową odpowiedź.

    Zrzut ekranu przedstawiający okno Programu Team Explorer. Test TestWatchFunctionSuccess zakończył się niepowodzeniem.

W tej lekcji pokazano, jak utworzyć projekt testu jednostkowego i zaimplementować testy jednostkowe dla funkcji platformy Azure.