-
-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using google.protobuf.Empty as response results in a bad gRPC response #1144
Comments
@ArcaneTSGK Thanks for noticing this. This is a new scenario I never tested. I'll keep you informed on the progress... |
@ArcaneTSGK And what should actually be the behavior of WireMock.Net if a google.protobuf.Empty is a return value? |
@StefH There are a number of them yes, For Empty return value it's Converting Empty to JSON would represent an empty JSON object {} Here are all of Googles Well Known types: https://protobuf.dev/reference/protobuf/google.protobuf/ https://protobuf.dev/reference/protobuf/google.protobuf/#empty Returning any of the scalar types in protobuf within a custom response that maps to a C# type is fine except for 'Enum'. I've not tried the 'Any' well-known type as my application doesn't have use for it, but I imagine that one might cause some issues, also when working with nullable types you use 'OneOf', again I haven't had to use these so I do not know if they'll work, but this is what a proto file would look like using those: Usage of 'Any' syntax = "proto3";
package tutorial;
import "include/google/protobuf/any.proto"
message Animal {
string name=1;
int32 age=2;
google.protobuf.Any care_giver=3;
}
message Owner {
int32 id=1;
string first_name=2;
string last_name=3;
}
message Foster {
int32 id=1;
string address=2;
} In that example a care give can be any pre-defined message in the proto, which could be Owner or the Foster, so that might be a test case for Wiremock to see if Any maps back, and lastly OneOf for nullables where you'd need to be able to allow a null return in the response: And this is OneOf import "google/protobuf/struct.proto";
package tutorial;
option csharp_namespace = "MyExample.Dog";
message Dog {
google.protobuf.Int32Value id=1;
string name=2;
NullableField profile_picture=3;
}
message NullableField {
oneof kind {
google.protobuf.NullValue null=1;
google.protobuf.StringValue value=2;
}
} |
Currently I only have an easy way to support:
|
@ArcaneTSGK |
@ArcaneTSGK
|
I will have some time tomorrow to take a look, I'll let you know my results, thanks @StefH |
@ArcaneTSGK |
@ArcaneTSGK |
Hi @StefH sorry for the delay, Unfortunately, I can't install your prerelease version 1.5.62-ci-19067 as it does not resolve, are your pre-releases publicly available? I only have the option (with prereleases enabled) to install 1.5.62 or 1.60 / 1.61 |
Preview versions are defined on MyGet. But it could be that that specific version is automatically deleted because only x versions are kept on MyGet. I will take a look and maybe I need to build a new preview. |
No worries, I've added MyGet as a feed and will await the specific version with the gRPC fix to test |
@ArcaneTSGK |
So I attempted to use this build and I get the following exception: (Status(StatusCode="Internal", Detail="Failed to deserialize response message.") The proto file looks like this
The test is setup as follows:
I did try Duration and Timestamp aswell but those were returning unimplemented for me when I was using Let me know if I'm missing anything I also tried the fully qualified name of Google.Protobuf.WellKnownTypes.Empty as the message type to no avail. Thanks |
Strange, I did add a unit test https://github.com/WireMock-Net/WireMock.Net/blob/bug/1144-protobuf/test/WireMock.Net.Tests/Grpc/WireMockServerTests.Grpc.cs#L104 proto private const string ProtoDefinitionWithWellKnownTypes = @"
syntax = ""proto3"";
import ""google/protobuf/empty.proto"";
import ""google/protobuf/timestamp.proto"";
import ""google/protobuf/duration.proto"";
service Greeter {
rpc SayNothing (google.protobuf.Empty) returns (google.protobuf.Empty);
}
message MyMessageTimestamp {
google.protobuf.Timestamp ts = 1;
}
message MyMessageDuration {
google.protobuf.Duration du = 1;
}
"; Unit test code: // Arrange
var bytes = Convert.FromBase64String("CgRzdGVm");
using var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc/Greeter/SayNothing")
.WithBody(new NotNullOrEmptyMatcher())
)
.RespondWith(Response.Create()
.WithBodyAsProtoBuf(ProtoDefinitionWithWellKnownTypes, "google.protobuf.Empty",
new { }
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
// Act
var protoBuf = new ByteArrayContent(bytes);
protoBuf.Headers.ContentType = new MediaTypeHeaderValue("application/grpc-web");
var client = server.CreateClient();
var response = await client.PostAsync("/grpc/Greeter/SayNothing", protoBuf);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
Convert.ToBase64String(responseBytes).Should().Be("");
server.Stop(); What is the difference? |
I will have to provide a minimal reproduction solution when I have time, I've tried a few different things and for .Empty I always get the unable to deserialize response, and for duration/timestamp I'm getting the Unimplemented error. I'll provide a link to the repository and throw something together by the end of the week |
Using https://protobuf.heyenrath.nl/ with your message and |
Hello @ArcaneTSGK, could you make an example project to demonstrate this issue? |
1 similar comment
Hello @ArcaneTSGK, could you make an example project to demonstrate this issue? |
Hello,
|
@carlos-pilao-deltatre |
@StefH
|
You did check MyGet? |
yes |
try this |
Getting the same issue... |
1 and 3 are fixed. See preview version: |
Hello @carlos-pilao-deltatre / @ArcaneTSGK ; did you have time to validate that latest preview version? |
Hello @StefH , |
@samir-babachikj-deltatre You can use version Preview versions are defined on MyGet. |
@StefH I only have these versions available: |
Use this version |
@StefH The version you mentioned depends on: WireMock.Net.Abstractions 1.6.6-ci-19363, WireMock.Net.OpenApiParser 1.6.6-ci-19363 and WireMock.Org.Abstractions 1.6.6-ci-19363. |
I deleted all packages from MyGet and ran a new build. Now only 1.6.6-ci-19365 should be there. |
@StefH Tried now, and at least for |
That's very strange. Will actually be the same logic, both are well defined google elements. Using this proto: syntax = "proto3";
package greet;
import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";
service Greeter {
rpc Nothing (google.protobuf.Empty) returns (google.protobuf.Empty);
rpc SayHello (HelloRequest) returns (HelloReply);
rpc SayOther (Other) returns (HelloReply);
}
message HelloRequest {
string name = 1;
NullValue x = 2;
}
message Other {
string name = 1;
NullValue x = 2;
}
message HelloReply {
string message = 1;
}
message Person {
string name = 1;
int32 id = 2;
string email = 3;
} In https://protobuf.heyenrath.nl/ Can you please provide your .proto file? which has an issue ? |
@StefH The problem is the use of the Value type defined inside the struct.proto (ref. https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto). |
Can you try 1.6.6-ci-19366 ? |
@StefH It works now. Thank you! |
Hi @StefH , |
Yes, I think I made a mistake in that Value or Struct. I'll take a look. |
@samir-babachikj-deltatre |
@samir-babachikj-deltatre note that you need to use a Value this: |
@StefH It is working as expected now! Thank you🙏 |
@StefH the original issue of this thread still happening: if you have a service returning an empty response you cannot mock it. Tried several approaches like @ArcaneTSGK did without success. The only way I found so far is to create a custom response like VoidResponse and I need to have a field at least on it because if I return a structure without fields it will not work either :( |
It should work correctly. Can you please create a new issue with example code? |
When writing a response builder with
google.protobuf.Empty
the mock gRPC client will returnStatusCode=Unimplemented
.Expected behavior:
It should be possible to use googles 'WellKnown' types as the protobuf body in the response builder.
Test to reproduce
I have tried with and without the
.WithTransformer()
, I have also tried withnew Empty()
new Empty {}
andnew()
but none of those match.Other related info
I am able to get the tests to work if the response is a type that I create in my proto, for example lets say that the HelloReply is in the proto file with a
message HelloReply { string reply_message = 1; }
I have also tried creating my own
message EmptyResponse { }
and this also did not workIt only works when the response contains something like
I have also tried creating my own
message EmptyResponse { string status = 1; }
Please can someone either point me in the direction of what I am doing wrong to match an empty response, or confirm that this is a bug
Thanks
The text was updated successfully, but these errors were encountered: