I want to test client and thus mocking server by gmock.
My proto is defined as
// The greeting service definition.
service Greeter {
// Streaming request and reply
rpc StreamRequestAndReply (stream Request) returns (stream Reply) {}
}
message Request {
int32 idx = 1;
bool is_pause = 2; // control message
}
message Reply {
string msg = 1;
bool is_eof = 2;
}
And the correspinding function on server-side looks like
Status StreamRequestAndReply(ServerContext *context, ServerReaderWriter<Reply, Request> *stream) override {
// do something
}
My question is: how to write my predefined Reply message via the mocked stub by gmock, for example I want to reply three valid message and then set is_eof in the fourth one?
My current thinking is using testing::Invoke, but haven't figured out how to capture the stream and call the Write function. Can someone give me some suggestions and hints?
Synchronous gRPC provides virtual functions for all interfaces, which could be mocked by StubInterface.
Asynchronous gRPC (i.e. CompletionQueue) doesn't provide such functionality, since it's just a thin wrapper around C implementation. In this case, better to set-up a local fake server, and unit test it in an integration-like way.
Related
I have an application that defines a type Client struct {} which talks to various other clients in my code that talk to services like github, elasticsearch etc.
Now I have the following ES code in one of my packages
type SinkService interface {
Write(context, index, mapping, doc)
}
type ESSink struct {
client *elastic.Client
}
func NewESSink() *ESSink {}
// checks if the index exists and writes the doc
func (s *ESSink) Write(context, index, mapping, doc) {}
I use this method in my main client that runs the whole application like this c.es.Write(...). Now if I want to write client_test.go I can simply make a mockESSink and use it with some stub code but that won't cover the lines written in my ES code.
How do I unit test my ES code? My ESSink uses an elastic.Client. How do I mock that?
I would like to embed some mock ES client that gives me stub responses and I will be able to test my ESSink.Write method that way.
Based on your question, I assume you're using github.com/olivere/elastic, and you want to be able to test by using stub http responses. When I first read this question, I also have never written Go test code that use ES client. So, in addition to answering this question, I'm also sharing how I find out the answer from the godocs.
First, we can see that elastic.NewClient accepts client option functions. So I checked what kind of client option functions the library provides. Turns out the library provides elastic.SetHttpClient that accepts elastic.Doer. The Doer is an interface that http.Client can implement. From here, the answer becomes clear.
So, you have to:
Change your func NewESSink() to accept http Client or elastic Client.
Write stub http Client (implements elastic.Doer).
ESSink
type ESSink struct {
client *elastic.Client
}
func NewESSink(client *elastic.Client) *ESSink {
return &ESSink{client: client}
}
Stub HttpClient
package stubs
import "net/http"
type HTTPClient struct {
Response *http.Response
Error error
}
func (c *HTTPClient) Do(*http.Request) (*http.Response, error) {
return c.Response, c.Error
}
Your testing code
func TestWrite(t *testing.T) {
// set the body and error according to your test case
stubHttpClient := stubs.HTTPClient{
Response: &http.Response{Body: ...},
Error: ...,
}
elasticClient := elastic.NewClient(elastic.SetHttpClient(stubHttpClient))
esSink := NewESSink(elasticClient)
esSink.Write(...)
}
In your production code, you can use http.Client{} when setting ES http client.
I have the below method which uses websocket connection to send request,
public void sendLoginRequest(){
WebSocket webSocket = webSocketConnection.getSocketConnection();
Thread.sleep(300 * 1000);
JSONObject loginJson = new JSONObject();
loginJson.put("username","test");
webSocket.sendText(loginJson.toString());
}
I have created my tested case with,
#Test
public void testSendLoginRequest() {
obj.sendLoginRequest();
}
Due to Thread.sleep, it's waiting for 5 min. I'm just curious to control this flow, and make sure the data send to websocket. As far as i know verify method invokes on Mock object, but in this case how can i achieve it.
P.S: I use com.refinitiv.qc.ert.infrastructure.socket.WebSocketConnection API.
I have a class Communicator that tests whether it can connect the test server. Here is how I call it:
class CommunicatorTest
{
public:
CommunicatorTest() {}
bool doTest()
{
bool _success;
Parameters params;
Communicator communicator;
communicator.connect(params, [this, &_success](bool success)
{
statusCode = errorCode;
m_condition.notify_one();
});
std::unique_lock<std::mutex> uGuard(m_mutex);
m_condition.wait(uGuard);
return _success;
}
private:
std::mutex m_mutex;
std::condition_variable m_condition;
};
bool communicatorTest()
{
CommunicatorTest test;
bool success = test.doTest();
return success;
}
TEST(CommunicatorTest, test_eq)
{
EXPECT_EQ(communicatorTest(), true);
}
I tried to use condition and mutex to make this code synchronous but it fails, the logs say only that test was running and immediately finishes.
Is there a way to test success variable from the callback using google tests?
Thanks in advance.
In those cases the best solution is to create a mock that emulates the behavior of the server. You should not rely (unless extremely necessary) in external states when running your tests.
The tests may fail because the server is not connected, there is no internet connection or whatever condition.
You can use something like Google Mock, now part of Google Test suite to emulate the behavior:
class MockServer : public Server {
public:
MOCK_METHOD2(DoConnect, bool());
....
};
Then do something like this:
TEST(ServerTest, CanConnect) {
MockServer s;
EXPECT_CALL(s, DoConnect())
..WillOnce(Return(true));
EXPECT_TRUE(server.isConnected());
}
You can simulate the error handling:
TEST(ServerTest, CannotConnect) {
MockServer s;
EXPECT_CALL(s, DoConnect())
..WillOnce(Return(false));
EXPECT_FALSE(server.isConnected());
// ... Check the rest of your variables or states that may be false and
// check that the error handler is working properly
}
As someone who writes asynchronous code, I have stumbled upon this problem many times - it seems most existing C/C++ test frameworks don't have real support for testing asynchronous code. What is mainly needed is a event loop where you can schedule things to be executed (to mock timed external events, etc), and a mechanism to register responses and optionally check the order in which they occur. So, instead of trying to somehow adopt an existing framework (which would result in probably greater effort), I created my own one. I have been using it to test a javascript-like promise class that I have developed, and it's done the job good for me. If you are interested, I have just published it on GitHub:
https://github.com/alxvasilev/async-test
I come from python and I have been looking for a way to write yests in go. I have come across a few things on SO but they all seem very cumbersome and verbose for something that shpuld be needed all the time.
I am typing on mobile now, will add code later if needed...but for example...
say i have a function that calls smtp.Send somewhere in the middle. how can I easily test this function?
Say i have another one that hits some outside api (needs mocking) and then takes the response and calls something like ioutil.Readall()...how could i make my way through this test function and mock the call to the api and then pass some fake response data when Readall is called?
You can do it by using an interface. For example let's say you have an interface called Mailer:
type Mailer interface {
Send() error
}
Now you can embed a Mailer object into the function that calls the Send method.
type Processor struct {
Mailer
}
func (p *Processor) Process() {
_ = p.Mailer.Send()
}
Now in your test you can create a mock Mailer.
type mockMailer struct{}
//implement the Send on the mockMailer as you wish
p := &Processor{
Mailer: mockMailer,
}
p.Process()
when p.Process reaches the Send method it calls your mocked Send method.
I have exposed the soap web services using the cxf in mulesoft and this is my interface and java code.
Interface is:
#WebService
public interface HelloWorld {
String sayHi(String text);
}
The java class is:
#WebService(endpointInterface = "demo.HelloWorld",
serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
/*
Here i am writing the logic which is takes the 15 seconds
and i do not want that caller webservices must be wait to finish
this process.
*/
return "Hello " + text;
}
}
The currently the caller is waiting for finishing the all logic in the
sayHI() method but i want to do in asynchronous way its means the sayHi() method continuous the process and caller is not wait for response. So any idea how i can achieve in mulesoft?.
This is an reference in mule soft:
https://docs.mulesoft.com/mule-user-guide/v/3.7/building-web-services-with-cxf
Did you considered using flow processing strategy and tuning your threads ? :
https://docs.mulesoft.com/mule-user-guide/v/3.7/flow-processing-strategies
https://docs.mulesoft.com/mule-fundamentals/v/3.7/flows-and-subflows
http://blogs.mulesoft.com/dev/mule-dev/asynchronous-message-processing-with-mule/
and in the flow you can also use block after your Http listener for making it asynchronous :-
https://docs.mulesoft.com/mule-user-guide/v/3.7/async-scope-reference