1111from unittest .mock import Mock , patch
1212
1313import pytest
14- import requests
14+ from urllib .error import HTTPError , URLError
15+
1516from botocore .exceptions import ConnectionError # type: ignore
1617
1718from aws_durable_execution_sdk_python_testing .cli import CliApp , CliConfig , main
@@ -604,14 +605,21 @@ def test_invoke_command_makes_http_request_to_start_execution_endpoint() -> None
604605 """Test that invoke command makes HTTP request to start-durable-execution endpoint."""
605606 app = CliApp ()
606607
607- with patch ("requests.post" ) as mock_post :
608- # Mock successful response
609- mock_response = mock_post .return_value
610- mock_response .status_code = 201
611- mock_response .json .return_value = {
608+ response_body = json .dumps (
609+ {
612610 "ExecutionArn" : "arn:aws:lambda:us-west-2:123456789012:function:test-function:execution:test-execution"
613611 }
612+ ).encode ("utf-8" )
613+
614+ mock_response = Mock ()
615+ mock_response .read .return_value = response_body
616+ mock_response .__enter__ = Mock (return_value = mock_response )
617+ mock_response .__exit__ = Mock (return_value = False )
614618
619+ with patch (
620+ "aws_durable_execution_sdk_python_testing.cli.urlopen" ,
621+ return_value = mock_response ,
622+ ) as mock_urlopen :
615623 with patch ("sys.stdout" , new_callable = StringIO ) as mock_stdout :
616624 exit_code = app .invoke_command (
617625 argparse .Namespace (
@@ -622,16 +630,17 @@ def test_invoke_command_makes_http_request_to_start_execution_endpoint() -> None
622630 )
623631
624632 assert exit_code == 0
625- mock_post .assert_called_once ()
633+ mock_urlopen .assert_called_once ()
626634
627635 # Verify the request details
628- call_args = mock_post .call_args
629- assert call_args [0 ][0 ].endswith ("/start-durable-execution" )
630- assert call_args [1 ]["headers" ]["Content-Type" ] == "application/json"
636+ call_args = mock_urlopen .call_args
637+ req = call_args [0 ][0 ]
638+ assert req .full_url .endswith ("/start-durable-execution" )
639+ assert req .get_header ("Content-type" ) == "application/json"
631640 assert call_args [1 ]["timeout" ] == 30
632641
633642 # Verify payload structure
634- payload = call_args [ 1 ][ " json" ]
643+ payload = json . loads ( req . data . decode ( "utf-8" ))
635644 assert payload ["FunctionName" ] == "test-function"
636645 assert payload ["Input" ] == '{"key": "value"}'
637646 assert payload ["ExecutionName" ] == "test-execution"
@@ -645,11 +654,16 @@ def test_invoke_command_uses_default_execution_name_when_not_provided() -> None:
645654 """Test that invoke command generates default execution name when not provided."""
646655 app = CliApp ()
647656
648- with patch ("requests.post" ) as mock_post :
649- mock_response = mock_post .return_value
650- mock_response .status_code = 201
651- mock_response .json .return_value = {"ExecutionArn" : "test-arn" }
657+ response_body = json .dumps ({"ExecutionArn" : "test-arn" }).encode ("utf-8" )
658+ mock_response = Mock ()
659+ mock_response .read .return_value = response_body
660+ mock_response .__enter__ = Mock (return_value = mock_response )
661+ mock_response .__exit__ = Mock (return_value = False )
652662
663+ with patch (
664+ "aws_durable_execution_sdk_python_testing.cli.urlopen" ,
665+ return_value = mock_response ,
666+ ) as mock_urlopen :
653667 app .invoke_command (
654668 argparse .Namespace (
655669 function_name = "my-function" ,
@@ -659,18 +673,17 @@ def test_invoke_command_uses_default_execution_name_when_not_provided() -> None:
659673 )
660674
661675 # Verify default execution name is generated
662- payload = mock_post .call_args [1 ]["json" ]
676+ req = mock_urlopen .call_args [0 ][0 ]
677+ payload = json .loads (req .data .decode ("utf-8" ))
663678 assert payload ["ExecutionName" ] == "my-function-execution"
664679
665680
666681def test_invoke_command_handles_connection_error () -> None :
667682 """Test that invoke command handles connection errors gracefully."""
668683 app = CliApp ()
669684
670- with patch ("requests.post" ) as mock_post :
671- mock_post .side_effect = requests .exceptions .ConnectionError (
672- "Connection refused"
673- )
685+ with patch ("aws_durable_execution_sdk_python_testing.cli.urlopen" ) as mock_urlopen :
686+ mock_urlopen .side_effect = URLError ("Connection refused" )
674687
675688 exit_code = app .invoke_command (
676689 argparse .Namespace (
@@ -687,8 +700,8 @@ def test_invoke_command_handles_timeout_error() -> None:
687700 """Test that invoke command handles timeout errors gracefully."""
688701 app = CliApp ()
689702
690- with patch ("requests.post " ) as mock_post :
691- mock_post .side_effect = requests . exceptions . Timeout ("Request timed out" )
703+ with patch ("aws_durable_execution_sdk_python_testing.cli.urlopen " ) as mock_urlopen :
704+ mock_urlopen .side_effect = TimeoutError ("Request timed out" )
692705
693706 exit_code = app .invoke_command (
694707 argparse .Namespace (
@@ -705,13 +718,21 @@ def test_invoke_command_handles_http_error_response() -> None:
705718 """Test that invoke command handles HTTP error responses."""
706719 app = CliApp ()
707720
708- with patch ("requests.post" ) as mock_post :
709- mock_response = mock_post .return_value
710- mock_response .status_code = 400
711- mock_response .json .return_value = {
721+ error_body = json .dumps (
722+ {
712723 "ErrorMessage" : "Invalid parameter value" ,
713724 "ErrorType" : "InvalidParameterValueException" ,
714725 }
726+ ).encode ("utf-8" )
727+
728+ with patch ("aws_durable_execution_sdk_python_testing.cli.urlopen" ) as mock_urlopen :
729+ mock_urlopen .side_effect = HTTPError (
730+ url = "http://0.0.0.0:5000/start-durable-execution" ,
731+ code = 400 ,
732+ msg = "Bad Request" ,
733+ hdrs = {},
734+ fp = __import__ ("io" ).BytesIO (error_body ),
735+ )
715736
716737 with patch ("sys.stderr" , new_callable = StringIO ) as mock_stderr :
717738 exit_code = app .invoke_command (
@@ -730,11 +751,14 @@ def test_invoke_command_handles_non_json_error_response() -> None:
730751 """Test that invoke command handles non-JSON error responses."""
731752 app = CliApp ()
732753
733- with patch ("requests.post" ) as mock_post :
734- mock_response = mock_post .return_value
735- mock_response .status_code = 500
736- mock_response .json .side_effect = json .JSONDecodeError ("Invalid JSON" , "" , 0 )
737- mock_response .text = "Internal Server Error"
754+ with patch ("aws_durable_execution_sdk_python_testing.cli.urlopen" ) as mock_urlopen :
755+ mock_urlopen .side_effect = HTTPError (
756+ url = "http://0.0.0.0:5000/start-durable-execution" ,
757+ code = 500 ,
758+ msg = "Internal Server Error" ,
759+ hdrs = {},
760+ fp = __import__ ("io" ).BytesIO (b"Internal Server Error" ),
761+ )
738762
739763 exit_code = app .invoke_command (
740764 argparse .Namespace (
@@ -1050,8 +1074,8 @@ def test_invoke_command_handles_general_exception() -> None:
10501074 """Test that invoke command handles general exceptions."""
10511075 app = CliApp ()
10521076
1053- with patch ("requests.post " ) as mock_post :
1054- mock_post .side_effect = ValueError ("Some unexpected error" )
1077+ with patch ("aws_durable_execution_sdk_python_testing.cli.urlopen " ) as mock_urlopen :
1078+ mock_urlopen .side_effect = ValueError ("Some unexpected error" )
10551079
10561080 exit_code = app .invoke_command (
10571081 argparse .Namespace (
0 commit comments