Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Testowanie jednostkowe jest ważną częścią nowoczesnych praktyk programistycznych. Testy jednostkowe weryfikują zachowanie logiki biznesowej i chronią przed wprowadzeniem niezauważonych zmian zakłócających działanie w przyszłości. Durable Functions mogą łatwo zwiększyć złożoność, dlatego wprowadzenie testów jednostkowych pomaga uniknąć zmian powodujących niezgodność. W poniższych sekcjach opisano sposób testowania jednostkowego trzech typów funkcji — klienta orkiestracji, orkiestratora i funkcji jednostki.
Uwaga / Notatka
Ten przewodnik dotyczy tylko aplikacji Durable Functions napisanych w modelu programowania w języku Python w wersji 2.
Wymagania wstępne
Przykłady w tym artykule wymagają znajomości następujących pojęć i struktur:
- Testowanie jednostek
- Funkcje trwałe
- Test jednostkowy języka Python
- unittest.mock
Konfigurowanie środowiska testowego
Aby przetestować rozszerzenie Durable Functions, ważne jest skonfigurowanie odpowiedniego środowiska testowego. Obejmuje to utworzenie katalogu testowego i zainstalowanie modułu języka unittest Python w środowisku języka Python. Aby uzyskać więcej informacji, zobacz Omówienie testowania jednostkowego języka Python w usłudze Azure Functions.
Funkcje wyzwalacza testów jednostkowych
Funkcje wyzwalacza, często nazywane funkcjami klienta , inicjują aranżacje i zdarzenia zewnętrzne. Aby przetestować te funkcje:
- Mockuj
DurableOrchestrationClient, aby symulować wykonywanie i zarządzanie stanem orkiestracji. - Przypisz
DurableOrchestrationClientmetody, takie jakstart_new,get_statuslubraise_eventz pozornymi funkcjami, które zwracają oczekiwane wartości. - Wywołaj funkcję klienta bezpośrednio za pomocą symulowanego klienta i innych niezbędnych argumentów, takich jak
req(obiekt żądania HTTP) dla funkcji klienta wyzwalacza HTTP. - Użyj asercji i narzędzi
unittest.mockdo zweryfikowania oczekiwanego działania przy rozpoczęciu orkiestracji, parametrów i odpowiedzi HTTP.
import asyncio
import unittest
import azure.functions as func
from unittest.mock import AsyncMock, Mock, patch
from function_app import start_orchestrator
class TestFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableOrchestrationClient')
def test_HttpStart(self, client):
# Get the original method definition as seen in the function_app.py file
func_call = http_start.build().get_user_function().client_function
req = func.HttpRequest(method='GET',
body=b'{}',
url='/api/my_second_function',
route_params={"functionName": "my_orchestrator"})
client.start_new = AsyncMock(return_value="instance_id")
client.create_check_status_response = Mock(return_value="check_status_response")
# Execute the function code
result = asyncio.run(func_call(req, client))
client.start_new.assert_called_once_with("my_orchestrator")
client.create_check_status_response.assert_called_once_with(req, "instance_id")
self.assertEqual(result, "check_status_response")
Funkcje orkiestratora testów jednostkowych
Funkcje programu Orchestrator zarządzają wykonywaniem wielu funkcji działań. Aby przetestować orchestratora:
- Zamockuj
DurableOrchestrationContextw celu kontrolowania wykonywania funkcji. - Zastąp
DurableOrchestrationContextmetody potrzebne do wykonywania orkiestratora, takie jakcall_activitylubcreate_timer, funkcjami symulacyjnymi. Te funkcje zwykle zwracają obiekty typu TaskBase z właściwościąresult. - Wywołaj koordynatora rekursywnie, przekazując wynik zadania wygenerowanego przez poprzednią instrukcję yield do następnego.
- Sprawdź wynik orkiestratora, porównując go z wynikami zwróconymi przez orkiestrator i
unittest.mock.
import unittest
from unittest.mock import Mock, patch, call
from datetime import timedelta
from azure.durable_functions.testing import orchestrator_generator_wrapper
from function_app import my_orchestrator
class TestFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableOrchestrationContext')
def test_chaining_orchestrator(self, context):
# Get the original method definition as seen in the function_app.py file
func_call = my_orchestrator.build().get_user_function().orchestrator_function
# The mock_activity method is defined above with behavior specific to your app.
# It returns a TaskBase object with the result expected from the activity call.
context.call_activity = Mock(side_effect=mock_activity)
# Create a generator using the method and mocked context
user_orchestrator = func_call(context)
# Use orchestrator_generator_wrapper to get the values from the generator.
# Processes the orchestrator in a way that is equivalent to the Durable replay logic
values = [val for val in orchestrator_generator_wrapper(user_orchestrator)]
expected_activity_calls = [call('say_hello', 'Tokyo'),
call('say_hello', 'Seattle'),
call('say_hello', 'London')]
self.assertEqual(context.call_activity.call_count, 3)
self.assertEqual(context.call_activity.call_args_list, expected_activity_calls)
self.assertEqual(values[3], ["Hello Tokyo!", "Hello Seattle!", "Hello London!"])
Funkcje jednostek testowania jednostkowego
Funkcje jednostek zarządzają obiektami stanowymi za pomocą operacji. Aby przetestować funkcję jednostki:
- Zmockuj
DurableEntityContextw celu zasymulowania wewnętrznego stanu i danych wejściowych operacji jednostki. - Zastąp
DurableEntityContextmetody, takie jakget_state,set_stateioperation_name, makietami, które zwracają kontrolowane wartości. - Wywołaj funkcję jednostki bezpośrednio z wyśmiewanym kontekstem.
- Użyj asercji, aby zweryfikować zmiany stanu i zwrócone wartości, wraz z wykorzystaniem narzędzi
unittest.mock.
import unittest
from unittest.mock import Mock, patch
from function_app import Counter
class TestEntityFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableEntityContext')
def test_entity_add_operation(self, context_mock):
# Get the original method definition as seen in function_app.py
func_call = Counter.build().get_user_function().entity_function
# Setup mock context behavior
state = 0
result = None
def set_state(new_state):
nonlocal state
state = new_state
def set_result(new_result):
nonlocal result
result = new_result
context_mock.get_state = Mock(return_value=state)
context_mock.set_state = Mock(side_effect=set_state)
context_mock.operation_name = "add"
context_mock.get_input = Mock(return_value=5)
context_mock.set_result = Mock(side_effect=lambda x: set_result)
# Call the entity function with the mocked context
func_call(context_mock)
# Verify the state was updated correctly
context_mock.set_state.assert_called_once_with(5)
self.assertEqual(state, 5)
self.assertEqual(result, None)
Funkcje działania testowania jednostkowego
Funkcje działania można testować bez wprowadzania modyfikacji specyficznych dla Durable. Wskazówki zawarte w przeglądzie testów jednostkowych języka Python w usłudze Azure Functions są wystarczające do testowania tych funkcji.