Ćwiczenie — test jednostkowy funkcji platformy Azure
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.
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.
W oknie Dodawanie nowego projektu przewiń w dół, wybierz szablon ikony XUnit Test Project C#+, a następnie wybierz przycisk Dalej.
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.
Wybierz Dalej. Zostanie wyświetlone okno Dodatkowe informacje .
W obszarze Platforma docelowa. Zaakceptuj wartość domyślną platformy .NET 6.0 (obsługa długoterminowa).
Wybierz pozycję Utwórz.
Po dodaniu projektu kliknij prawym przyciskiem myszy projekt WatchFunctionTests w oknie Eksplorator rozwiązań, a następnie wybierz polecenie Zarządzaj pakietami NuGet.
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.
Uwaga
W projekcie testowym zostanie utworzone pozorne środowisko HTTP. Pakiet Microsoft.AspNetCore.Mvc zawiera klasy wymagane do tego celu.
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ę.
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.
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.
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.
W oknie Eksplorator rozwiązań, aby wyświetlić element WatchPortalFunction w oknie kodu, kliknij dwukrotnie plik WatchFunctionUnitTests.cs.
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;
Zmień nazwę metody Test1 na TestWatchFunctionSuccess.
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 } } ) };
Dodaj następującą instrukcję do metody. Ta instrukcja tworzy fikcyjny rejestrator.
var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
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();
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); }
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
Na górnym pasku menu w obszarze Test wybierz pozycję Uruchom wszystkie testy.
W oknie Eksplorator testów wszystkie trzy testy powinny zakończyć się pomyślnie.
W oknie Eksplorator rozwiązań w projekcie WatchPortalFunction kliknij dwukrotnie plik WatchInfo.cs, aby wyświetlić go w edytorze kodu.
Znajdź następujący kod.
// Retrieve the model id from the query string string model = req.Query["model"];
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"];
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ź.
W tej lekcji pokazano, jak utworzyć projekt testu jednostkowego i zaimplementować testy jednostkowe dla funkcji platformy Azure.