Skip to content

Commit fe5cd68

Browse files
committed
add test for bug where request body is not passed
1 parent 07faa49 commit fe5cd68

2 files changed

Lines changed: 240 additions & 0 deletions

File tree

‎packages/gapic-generator/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2‎

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,145 @@ async def test_{{ service.name|snake_case }}_{{ method.name|snake_case }}_rest_a
17041704
assert isinstance(result, {{ method.output.ident }})
17051705
assert result == expected_result
17061706
{% endif %}
1707+
1708+
1709+
def test_{{ service.name|snake_case }}_{{ method.name|snake_case }}_rest_body_and_query_params():
1710+
client = {{ service.client_name }}(
1711+
credentials=ga_credentials.AnonymousCredentials(),
1712+
transport="rest",
1713+
)
1714+
with mock.patch.object(type(client.transport._session), "request") as req, mock.patch.object(
1715+
path_template, "transcode"
1716+
) as transcode:
1717+
request = {{ method.input.ident }}(
1718+
{% for field in method.input.fields.values() | rejectattr('message') %}
1719+
{% if not field.oneof or field.proto3_optional %}
1720+
{{ field.name }}={{ field.mock_value }},
1721+
{% endif %}
1722+
{% endfor %}
1723+
)
1724+
{% if method.input.ident.is_proto_plus_type %}
1725+
pb_request = {{ method.input.ident }}.pb(request)
1726+
{% else %}
1727+
pb_request = request
1728+
{% endif %}
1729+
transcode.return_value = {
1730+
"uri": "v1/sample_method",
1731+
"method": "{{ method.http_options[0].method }}",
1732+
"body": pb_request,
1733+
"query_params": pb_request,
1734+
}
1735+
1736+
start_response = mock.MagicMock()
1737+
start_response.ok = True
1738+
start_response.status_code = 200
1739+
start_response.headers = {"x-goog-upload-status": "active", "x-goog-upload-url": "http://localhost/upload"}
1740+
start_response.content = b""
1741+
1742+
expected_result = {{ method.output.ident }}()
1743+
{% if method.output.ident.is_proto_plus_type %}
1744+
json_return_value = {{ method.output.ident }}.to_json(expected_result)
1745+
{% else %}
1746+
json_return_value = json_format.MessageToJson(expected_result)
1747+
{% endif %}
1748+
upload_response = mock.MagicMock()
1749+
upload_response.ok = True
1750+
upload_response.status_code = 200
1751+
upload_response.headers = {"x-goog-upload-status": "final"}
1752+
upload_response.content = json_return_value.encode("UTF-8")
1753+
1754+
req.side_effect = [start_response, upload_response]
1755+
response = client.{{ method.client_method_name|snake_case }}(request)
1756+
result = response.upload(b"test data")
1757+
assert result == expected_result
1758+
1759+
start_call = req.call_args_list[0]
1760+
{% for field in method.input.fields.values() | rejectattr('message') %}
1761+
{% if not field.oneof or field.proto3_optional %}
1762+
assert "{{ field.name | camel_case }}=" in start_call.args[1]
1763+
{% endif %}
1764+
{% endfor %}
1765+
{% if method.http_options[0].body %}
1766+
expected_body = json_format.MessageToJson(
1767+
pb_request,
1768+
use_integers_for_enums={{ opts.rest_numeric_enums }},
1769+
)
1770+
assert start_call.kwargs["data"] == expected_body.encode("UTF-8")
1771+
{% endif %}
1772+
1773+
1774+
{% if rest_async_io_enabled %}
1775+
@pytest.mark.asyncio
1776+
async def test_{{ service.name|snake_case }}_{{ method.name|snake_case }}_rest_asyncio_body_and_query_params():
1777+
if not HAS_ASYNC_REST_EXTRA:
1778+
pytest.skip()
1779+
client = {{ service.async_client_name }}(
1780+
credentials=async_anonymous_credentials(),
1781+
transport="rest_asyncio",
1782+
)
1783+
with mock.patch.object(
1784+
type(client.transport._session), "request", new_callable=mock.MagicMock
1785+
) as req, mock.patch.object(path_template, "transcode") as transcode:
1786+
request = {{ method.input.ident }}(
1787+
{% for field in method.input.fields.values() | rejectattr('message') %}
1788+
{% if not field.oneof or field.proto3_optional %}
1789+
{{ field.name }}={{ field.mock_value }},
1790+
{% endif %}
1791+
{% endfor %}
1792+
)
1793+
{% if method.input.ident.is_proto_plus_type %}
1794+
pb_request = {{ method.input.ident }}.pb(request)
1795+
{% else %}
1796+
pb_request = request
1797+
{% endif %}
1798+
transcode.return_value = {
1799+
"uri": "v1/sample_method",
1800+
"method": "{{ method.http_options[0].method }}",
1801+
"body": pb_request,
1802+
"query_params": pb_request,
1803+
}
1804+
1805+
start_response = mock.MagicMock()
1806+
start_response.status = 200
1807+
start_response.headers = {"x-goog-upload-status": "active", "x-goog-upload-url": "http://localhost/upload"}
1808+
start_response.read = mock.AsyncMock(return_value=b"")
1809+
start_ctx = mock.MagicMock()
1810+
start_ctx.__aenter__ = mock.AsyncMock(return_value=start_response)
1811+
start_ctx.__aexit__ = mock.AsyncMock(return_value=None)
1812+
1813+
expected_result = {{ method.output.ident }}()
1814+
{% if method.output.ident.is_proto_plus_type %}
1815+
json_return_value = {{ method.output.ident }}.to_json(expected_result)
1816+
{% else %}
1817+
json_return_value = json_format.MessageToJson(expected_result)
1818+
{% endif %}
1819+
upload_response = mock.MagicMock()
1820+
upload_response.status = 200
1821+
upload_response.headers = {"x-goog-upload-status": "final"}
1822+
upload_response.read = mock.AsyncMock(return_value=json_return_value.encode("UTF-8"))
1823+
upload_ctx = mock.MagicMock()
1824+
upload_ctx.__aenter__ = mock.AsyncMock(return_value=upload_response)
1825+
upload_ctx.__aexit__ = mock.AsyncMock(return_value=None)
1826+
1827+
req.side_effect = [start_ctx, upload_ctx]
1828+
response = await client.{{ method.client_method_name|snake_case }}(request)
1829+
result = await response.upload(b"test data")
1830+
assert result == expected_result
1831+
1832+
start_call = req.call_args_list[0]
1833+
{% for field in method.input.fields.values() | rejectattr('message') %}
1834+
{% if not field.oneof or field.proto3_optional %}
1835+
assert "{{ field.name | camel_case }}=" in start_call.args[1]
1836+
{% endif %}
1837+
{% endfor %}
1838+
{% if method.http_options[0].body %}
1839+
expected_body = json_format.MessageToJson(
1840+
pb_request,
1841+
use_integers_for_enums={{ opts.rest_numeric_enums }},
1842+
)
1843+
assert start_call.kwargs["data"] == expected_body.encode("UTF-8")
1844+
{% endif %}
1845+
{% endif %}
17071846
{% endfor %}
17081847
{% endif %}
17091848

‎packages/gapic-generator/tests/integration/goldens/showcase/tests/unit/gapic/showcase_v1beta1/test_resumable_upload_service.py‎

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,107 @@ async def test_resumable_upload_service_upload_media_rest_asyncio_start_empty_bo
24402440
assert result == expected_result
24412441

24422442

2443+
def test_resumable_upload_service_upload_media_rest_body_and_query_params():
2444+
client = ResumableUploadServiceClient(
2445+
credentials=ga_credentials.AnonymousCredentials(),
2446+
transport="rest",
2447+
)
2448+
with mock.patch.object(type(client.transport._session), "request") as req, mock.patch.object(
2449+
path_template, "transcode"
2450+
) as transcode:
2451+
request = resumable_upload.UploadMediaRequest(
2452+
name='name_value',
2453+
)
2454+
pb_request = resumable_upload.UploadMediaRequest.pb(request)
2455+
transcode.return_value = {
2456+
"uri": "v1/sample_method",
2457+
"method": "post",
2458+
"body": pb_request,
2459+
"query_params": pb_request,
2460+
}
2461+
2462+
start_response = mock.MagicMock()
2463+
start_response.ok = True
2464+
start_response.status_code = 200
2465+
start_response.headers = {"x-goog-upload-status": "active", "x-goog-upload-url": "http://localhost/upload"}
2466+
start_response.content = b""
2467+
2468+
expected_result = resumable_upload.UploadMediaResponse()
2469+
json_return_value = resumable_upload.UploadMediaResponse.to_json(expected_result)
2470+
upload_response = mock.MagicMock()
2471+
upload_response.ok = True
2472+
upload_response.status_code = 200
2473+
upload_response.headers = {"x-goog-upload-status": "final"}
2474+
upload_response.content = json_return_value.encode("UTF-8")
2475+
2476+
req.side_effect = [start_response, upload_response]
2477+
response = client.upload_media(request)
2478+
result = response.upload(b"test data")
2479+
assert result == expected_result
2480+
2481+
start_call = req.call_args_list[0]
2482+
assert "name=" in start_call.args[1]
2483+
expected_body = json_format.MessageToJson(
2484+
pb_request,
2485+
use_integers_for_enums=True,
2486+
)
2487+
assert start_call.kwargs["data"] == expected_body.encode("UTF-8")
2488+
2489+
2490+
@pytest.mark.asyncio
2491+
async def test_resumable_upload_service_upload_media_rest_asyncio_body_and_query_params():
2492+
if not HAS_ASYNC_REST_EXTRA:
2493+
pytest.skip()
2494+
client = ResumableUploadServiceAsyncClient(
2495+
credentials=async_anonymous_credentials(),
2496+
transport="rest_asyncio",
2497+
)
2498+
with mock.patch.object(
2499+
type(client.transport._session), "request", new_callable=mock.MagicMock
2500+
) as req, mock.patch.object(path_template, "transcode") as transcode:
2501+
request = resumable_upload.UploadMediaRequest(
2502+
name='name_value',
2503+
)
2504+
pb_request = resumable_upload.UploadMediaRequest.pb(request)
2505+
transcode.return_value = {
2506+
"uri": "v1/sample_method",
2507+
"method": "post",
2508+
"body": pb_request,
2509+
"query_params": pb_request,
2510+
}
2511+
2512+
start_response = mock.MagicMock()
2513+
start_response.status = 200
2514+
start_response.headers = {"x-goog-upload-status": "active", "x-goog-upload-url": "http://localhost/upload"}
2515+
start_response.read = mock.AsyncMock(return_value=b"")
2516+
start_ctx = mock.MagicMock()
2517+
start_ctx.__aenter__ = mock.AsyncMock(return_value=start_response)
2518+
start_ctx.__aexit__ = mock.AsyncMock(return_value=None)
2519+
2520+
expected_result = resumable_upload.UploadMediaResponse()
2521+
json_return_value = resumable_upload.UploadMediaResponse.to_json(expected_result)
2522+
upload_response = mock.MagicMock()
2523+
upload_response.status = 200
2524+
upload_response.headers = {"x-goog-upload-status": "final"}
2525+
upload_response.read = mock.AsyncMock(return_value=json_return_value.encode("UTF-8"))
2526+
upload_ctx = mock.MagicMock()
2527+
upload_ctx.__aenter__ = mock.AsyncMock(return_value=upload_response)
2528+
upload_ctx.__aexit__ = mock.AsyncMock(return_value=None)
2529+
2530+
req.side_effect = [start_ctx, upload_ctx]
2531+
response = await client.upload_media(request)
2532+
result = await response.upload(b"test data")
2533+
assert result == expected_result
2534+
2535+
start_call = req.call_args_list[0]
2536+
assert "name=" in start_call.args[1]
2537+
expected_body = json_format.MessageToJson(
2538+
pb_request,
2539+
use_integers_for_enums=True,
2540+
)
2541+
assert start_call.kwargs["data"] == expected_body.encode("UTF-8")
2542+
2543+
24432544
# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are
24442545
# removed from grpc/grpc_asyncio transport constructor.
24452546
@pytest.mark.filterwarnings("ignore::FutureWarning")

0 commit comments

Comments
 (0)