Skip to content

Commit 58df2da

Browse files
authored
tests: resolve failure related to unpacking dictionary for protobuf messages (#17273)
This PR resolves the following failure in #17245 ([build log](https://github.com/googleapis/google-cloud-python/actions/runs/26527262176/job/78134171625?pr=17245)) ``` ==================================== ERRORS ==================================== _ ERROR collecting tests/unit/gapic/bigtable_admin_v2/test_bigtable_instance_admin.py _ tests/unit/gapic/bigtable_admin_v2/test_bigtable_instance_admin.py:7259: in <module> iam_policy_pb2.GetIamPolicyRequest({}), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E TypeError: _AddInitMethod.<locals>.init() takes 1 positional argument but 2 were given _ ERROR collecting tests/unit/gapic/bigtable_admin_v2/test_bigtable_table_admin.py _ tests/unit/gapic/bigtable_admin_v2/test_bigtable_table_admin.py:11222: in <module> iam_policy_pb2.GetIamPolicyRequest({}), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E TypeError: _AddInitMethod.<locals>.init() takes 1 positional argument but 2 were given ``` To resolve the issue, this PR adds `**` to unpack fields as keyword arguments, maintaining compatibility with both proto-plus and pure protobuf messages.
1 parent 0d9abb3 commit 58df2da

15 files changed

Lines changed: 850 additions & 1040 deletions

File tree

packages/gapic-generator/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_macros.j2

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
{%- set auto_populated_field_sample_value = "explicit value for autopopulate-able field" -%}
55
{% with method_name = method.client_method_name|snake_case + "_unary" if method.extended_lro and not full_extended_lro else method.client_method_name|snake_case, method_output = method.extended_lro.operation_type if method.extended_lro and not full_extended_lro else method.output %}
66
@pytest.mark.parametrize("request_type", [
7-
{{ method.input.ident }}({
7+
{% if auto_populated_fields %}
8+
# Pure protobuf messages (non-proto-plus) require keyword arguments.
9+
{{ method.input.ident }}(**{
810
{% for auto_populated_field in auto_populated_fields %}
911
"{{ auto_populated_field }}": "{{ auto_populated_field_sample_value }}",
1012
{% endfor %}
@@ -14,6 +16,10 @@
1416
"{{ auto_populated_field }}": "{{ auto_populated_field_sample_value }}",
1517
{% endfor %}
1618
},
19+
{% else %}
20+
{{ method.input.ident }}(),
21+
{},
22+
{% endif %}
1723
])
1824
def test_{{ method_name }}(request_type, transport: str = 'grpc'):
1925
client = {{ service.client_name }}(
@@ -260,7 +266,9 @@ async def test_{{ method_name }}_async_use_cached_wrapped_rpc(transport: str = "
260266

261267
@pytest.mark.asyncio
262268
@pytest.mark.parametrize("request_type", [
263-
{{ method.input.ident }}({
269+
{% if auto_populated_fields %}
270+
# Pure protobuf messages (non-proto-plus) require keyword arguments.
271+
{{ method.input.ident }}(**{
264272
{%- for auto_populated_field in auto_populated_fields %}
265273
"{{ auto_populated_field }}": "{{ auto_populated_field_sample_value }}",
266274
{%- endfor %}
@@ -270,6 +278,10 @@ async def test_{{ method_name }}_async_use_cached_wrapped_rpc(transport: str = "
270278
"{{ auto_populated_field }}": "{{ auto_populated_field_sample_value }}",
271279
{%- endfor %}
272280
},
281+
{% else %}
282+
{{ method.input.ident }}(),
283+
{},
284+
{% endif %}
273285
])
274286
async def test_{{ method_name }}_async(request_type, transport: str = 'grpc_asyncio'):
275287
client = {{ service.async_client_name }}(
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
syntax = "proto3";
16+
17+
package google.cloud.location;
18+
19+
import "google/api/annotations.proto";
20+
import "google/protobuf/any.proto";
21+
import "google/api/client.proto";
22+
23+
option cc_enable_arenas = true;
24+
option go_package = "google.golang.org/genproto/googleapis/cloud/location;location";
25+
option java_multiple_files = true;
26+
option java_outer_classname = "LocationsProto";
27+
option java_package = "com.google.cloud.location";
28+
29+
// An abstract interface that provides location-related information for
30+
// a service. Service-specific metadata is provided through the
31+
// [Location.metadata][google.cloud.location.Location.metadata] field.
32+
service Locations {
33+
option (google.api.default_host) = "cloud.googleapis.com";
34+
option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform";
35+
36+
// Lists information about the supported locations for this service.
37+
rpc ListLocations(ListLocationsRequest) returns (ListLocationsResponse) {
38+
option (google.api.http) = {
39+
get: "/v1/{name=locations}"
40+
additional_bindings {
41+
get: "/v1/{name=projects/*}/locations"
42+
}
43+
};
44+
}
45+
46+
// Gets information about a location.
47+
rpc GetLocation(GetLocationRequest) returns (Location) {
48+
option (google.api.http) = {
49+
get: "/v1/{name=locations/*}"
50+
additional_bindings {
51+
get: "/v1/{name=projects/*/locations/*}"
52+
}
53+
};
54+
}
55+
}
56+
57+
// The request message for [Locations.ListLocations][google.cloud.location.Locations.ListLocations].
58+
message ListLocationsRequest {
59+
// The resource that owns the locations collection, if applicable.
60+
string name = 1;
61+
62+
// The standard list filter.
63+
string filter = 2;
64+
65+
// The standard list page size.
66+
int32 page_size = 3;
67+
68+
// The standard list page token.
69+
string page_token = 4;
70+
}
71+
72+
// The response message for [Locations.ListLocations][google.cloud.location.Locations.ListLocations].
73+
message ListLocationsResponse {
74+
// A list of locations that matches the specified filter in the request.
75+
repeated Location locations = 1;
76+
77+
// The standard List next-page token.
78+
string next_page_token = 2;
79+
}
80+
81+
// The request message for [Locations.GetLocation][google.cloud.location.Locations.GetLocation].
82+
message GetLocationRequest {
83+
// Resource name for the location.
84+
string name = 1;
85+
}
86+
87+
// A resource that represents Google Cloud Platform location.
88+
message Location {
89+
// Resource name for the location, which may vary between implementations.
90+
// For example: `"projects/example-project/locations/us-east1"`
91+
string name = 1;
92+
93+
// The canonical id for this location. For example: `"us-east1"`.
94+
string location_id = 4;
95+
96+
// The friendly name for this location, typically a nearby city name.
97+
// For example, "Tokyo".
98+
string display_name = 5;
99+
100+
// Cross-service attributes for the location. For example
101+
//
102+
// {"cloud.googleapis.com/region": "us-east1"}
103+
map<string, string> labels = 2;
104+
105+
// Service-specific metadata. For example the available capacity at the given
106+
// location.
107+
google.protobuf.Any metadata = 3;
108+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
syntax = "proto3";
16+
17+
package google.fragment;
18+
19+
import "google/api/client.proto";
20+
import "google/cloud/location/locations.proto";
21+
22+
service MockLocationService {
23+
option (google.api.default_host) = "locations.example.com";
24+
25+
rpc GetLocation(google.cloud.location.GetLocationRequest) returns (google.cloud.location.Location) {
26+
option (google.api.method_signature) = "name";
27+
}
28+
}

0 commit comments

Comments
 (0)