Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
Grpc
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
tci-gateway-module
Grpc
Commits
826b0029
Commit
826b0029
authored
7 years ago
by
Mahak Mukhi
Browse files
Options
Downloads
Patches
Plain Diff
Adding documentation for C++ unit tests
parent
a1c05910
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
doc/unit_testing.md
+175
-0
175 additions, 0 deletions
doc/unit_testing.md
with
175 additions
and
0 deletions
doc/unit_testing.md
0 → 100644
+
175
−
0
View file @
826b0029
# How to write unit tests for gRPC C client.
tl;dr:
[
Example code
](
https://github.com/grpc/grpc/blob/master/test/cpp/end2end/mock_test.cc
)
.
To unit-test client-side logic via the synchronous API, gRPC provides a mocked Stub based on googletest(googlemock) that can be programmed upon and easily incorporated in the test code.
For instance, consider an EchoService like this:
```
proto
service
EchoTestService
{
rpc
Echo
(
EchoRequest
)
returns
(
EchoResponse
);
rpc
BidiStream
(
stream
EchoRequest
)
returns
(
stream
EchoResponse
);
}
```
The code generated would look something like this:
```
c
class
EchoTestService
final
{
public:
class
StubInterface
{
virtual
::
grpc
::
Status
Echo
(
::
grpc
::
ClientContext
*
context
,
const
::
grpc
::
testing
::
EchoRequest
&
request
,
::
grpc
::
testing
::
EchoResponse
*
response
)
=
0
;
…
std
::
unique_ptr
<
::
grpc
::
ClientReaderWriterInterface
<
::
grpc
::
testing
::
EchoRequest
,
::
grpc
::
testing
::
EchoResponse
>>
BidiStream
(
::
grpc
::
ClientContext
*
context
)
{
return
std
::
unique_ptr
<
::
grpc
::
ClientReaderWriterInterface
<
::
grpc
::
testing
::
EchoRequest
,
::
grpc
::
testing
::
EchoResponse
>>
(
BidiStreamRaw
(
context
));
}
…
private:
virtual
::
grpc
::
ClientReaderWriterInterface
<
::
grpc
::
testing
::
EchoRequest
,
::
grpc
::
testing
::
EchoResponse
>*
BidiStreamRaw
(
::
grpc
::
ClientContext
*
context
)
=
0
;
…
}
// End StubInterface
…
}
// End EchoTestService
```
If we mock the StubInterface and set expectations on the pure-virtual methods we can test client-side logic without having to make any rpcs.
A mock for this StubInterface will look like this:
```
c
class
MockEchoTestServiceStub
:
public
EchoTestService
::
StubInterface
{
public:
MOCK_METHOD3
(
Echo
,
::
grpc
::
Status
(
::
grpc
::
ClientContext
*
context
,
const
::
grpc
::
testing
::
EchoRequest
&
request
,
::
grpc
::
testing
::
EchoResponse
*
response
));
MOCK_METHOD1
(
BidiStreamRaw
,
::
grpc
::
ClientReaderWriterInterface
<
::
grpc
::
testing
::
EchoRequest
,
::
grpc
::
testing
::
EchoResponse
>*
(
::
grpc
::
ClientContext
*
context
));
};
```
**Generating mock code:**
Such a mock can be auto-generated by:
1.
Setting flag(generate_mock_code=true) on grpc plugin for protoc, or
1.
Setting an attribute(generate_mock) in your bazel rule.
Protoc plugin flag:
```
sh
protoc
-I
.
--grpc_out
=
generate_mock_code
=
true
:.
--plugin
=
protoc-gen-grpc
=
`
which grpc_cpp_plugin
`
echo.proto
```
Bazel rule:
```
py
grpc_proto_library
(
name
=
"
echo_proto
"
,
srcs
=
[
"
echo.proto
"
],
generate_mock
=
True
,
)
```
By adding such a flag now a header file
`echo_mock.grpc.pb.h`
containing the mocked stub will also be generated.
This header file can then be included in test files along with a gmock dependency.
**Writing tests with mocked Stub.**
Consider the following client a user might have:
```
c
class
FakeClient
{
public:
explicit
FakeClient
(
EchoTestService
::
StubInterface
*
stub
)
:
stub_
(
stub
)
{}
void
DoEcho
()
{
ClientContext
context
;
EchoRequest
request
;
EchoResponse
response
;
request
.
set_message
(
"hello world"
);
Status
s
=
stub_
->
Echo
(
&
context
,
request
,
&
response
);
EXPECT_EQ
(
request
.
message
(),
response
.
message
());
EXPECT_TRUE
(
s
.
ok
());
}
void
DoBidiStream
()
{
EchoRequest
request
;
EchoResponse
response
;
ClientContext
context
;
grpc
::
string
msg
(
"hello"
);
std
::
unique_ptr
<
ClientReaderWriterInterface
<
EchoRequest
,
EchoResponse
>>
stream
=
stub_
->
BidiStream
(
&
context
);
request
.
set_message
(
msg
"0"
);
EXPECT_TRUE
(
stream
->
Write
(
request
));
EXPECT_TRUE
(
stream
->
Read
(
&
response
));
EXPECT_EQ
(
response
.
message
(),
request
.
message
());
request
.
set_message
(
msg
"1"
);
EXPECT_TRUE
(
stream
->
Write
(
request
));
EXPECT_TRUE
(
stream
->
Read
(
&
response
));
EXPECT_EQ
(
response
.
message
(),
request
.
message
());
request
.
set_message
(
msg
"2"
);
EXPECT_TRUE
(
stream
->
Write
(
request
));
EXPECT_TRUE
(
stream
->
Read
(
&
response
));
EXPECT_EQ
(
response
.
message
(),
request
.
message
());
stream
->
WritesDone
();
EXPECT_FALSE
(
stream
->
Read
(
&
response
));
Status
s
=
stream
->
Finish
();
EXPECT_TRUE
(
s
.
ok
());
}
void
ResetStub
(
EchoTestService
::
StubInterface
*
stub
)
{
stub_
=
stub
;
}
private:
EchoTestService
::
StubInterface
*
stub_
;
};
```
A test could initialize this FakeClient with a mocked stub having set expectations on it:
Unary RPC:
```
c
MockEchoTestServiceStub
stub
;
EchoResponse
resp
;
resp
.
set_message
(
"hello world"
);
Expect_CALL
(
stub
,
Echo
(
_
,
_
,
_
)).
Times
(
Atleast
(
1
)).
WillOnce
(
DoAll
(
SetArgPointee
<
2
>
(
resp
),
Return
(
Status
::
OK
)));
FakeClient
client
(
stub
);
client
.
DoEcho
();
```
Streaming RPC:
```
c
ACTION_P
(
copy
,
msg
)
{
arg0
->
set_message
(
msg
->
message
());
}
auto
rw
=
new
MockClientReaderWriter
<
EchoRequest
,
EchoResponse
>
();
EchoRequest
msg
;
EXPECT_CALL
(
*
rw
,
Write
(
_
,
_
)).
Times
(
3
).
WillRepeatedly
(
DoAll
(
SaveArg
<
0
>
(
&
msg
),
Return
(
true
)));
EXPECT_CALL
(
*
rw
,
Read
(
_
)).
WillOnce
(
DoAll
(
WithArg
<
0
>
(
copy
(
&
msg
)),
Return
(
true
))).
WillOnce
(
DoAll
(
WithArg
<
0
>
(
copy
(
&
msg
)),
Return
(
true
))).
WillOnce
(
DoAll
(
WithArg
<
0
>
(
copy
(
&
msg
)),
Return
(
true
))).
WillOnce
(
Return
(
false
));
MockEchoTestServiceStub
stub
;
EXPECT_CALL
(
stub
,
BidiStreamRaw
(
_
)).
Times
(
AtLeast
(
1
)).
WillOnce
(
Return
(
rw
));
FakeClient
client
(
stub
);
client
.
DoBidiStream
();
```
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment