How to test and mock a GRPC service written in Java using mockito - java

The protobuf definition is as follows:
syntax = "proto3";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
I need to use mockito along with junit testing !!

The idea is to stub the response and stream observer.
#Test
public void shouldTestGreeterService() throws Exception {
Greeter service = new Greeter();
HelloRequest req = HelloRequest.newBuilder()
.setName("hello")
.build();
StreamObserver<HelloRequest> observer = mock(StreamObserver.class);
service.sayHello(req, observer);
verify(observer, times(1)).onCompleted();
ArgumentCaptor<HelloReply> captor = ArgumentCaptor.forClass(HelloReply.class);
verify(observer, times(1)).onNext(captor.capture());
HelloReply response = captor.getValue();
assertThat(response.getStatus(), is(true));
}

The encouraged way to test a service is to use the in-process transport and a normal stub. Then you can communicate with the service like normal, without lots of mocking. Overused mocking produces brittle tests that don't instill confidence in the code being tested.
GrpcServerRule uses in-process transport behind-the-scenes. I suggest taking a look at the examples' tests, starting with hello world.

Related

how to test anonymous class object inside method

I'm writing unit cases using testNg and Mockito.The problem, I'm facing is with the method given below:
public void publishRequest(final NotificationRequest request){
MessageCreator messageCreator = new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
if (logger.isDebugEnabled()) {
logger.debug("Start of MessagePublisher publishRequest");
}
ObjectMessage msg = session.createObjectMessage();
msg.setStringProperty(
"SELECTOR",
request.getAvailaibilityTier() + "-"
+ request.getEsbReference());
if (logger.isDebugEnabled()) {
logger.debug("Message Selector=>"+msg.getStringProperty("SELECTOR"));
}
msg.setStringProperty(NotificationConstants.CACHE_KEY.name(),
request.getId());
msg.setObject(request.getData());
if (logger.isDebugEnabled()) {
logger.debug("Publishing request -->" + request);
}
if (logger.isDebugEnabled()) {
logger.debug("End of MessagePublisher publishRequest");
}
return msg;
}
};
producerTemplate.send(messageCreator);
}
While writing the unit case createMessage() method is not being called even if my test case creates the MessageCreater object. I want to include that also in my unit case to get the better coverage. Any Idea how to test inner class method?
It could be argued that the anynomous inner class is an implementation detail of the publishRequest method. When doing unit testing, you'll get more robust tests by testing the contract of publishRequest rather than the internal implementation. As #vtheron suggested, to test your MessageCreator, you have to extract it to it's own class. But in addition to that, consider "injecting" a reference to your MessageCreator in your class as well. That way, you can test both your publishRequest and MessageCreator in isolation. Personally, I prefer to "inject" such dependencies in a constructor, but there are other ways to achieve the same. I would do something like this:
public class MyClass {
private MessageCreator messageCreator;
public MyClass(MessageCreator messageCreator) {
this.messageCreator = messageCreator;
}
public void publishRequest(final NotificationRequest request) {
producerTemplate.send(messageCreator);
}
}
Then you can simply send a "Mock" MessageCreator to your class in a test:
public class MyTest {
#Test
public void testPublish() {
MessageCreator mock = new MessageCreator() { // Mock impl (or use a mock library)};
MyClass classToTest = new MyClass(mock);
classToTest.publishRequest(notificationRequest);
// Do assertions and verify
}
}
It's still testing the internals of your publishRequest method (testing void methods tends to), but if you can formulate a contract like
when a request is published, a message should be sent to a queue
rather than
publishRequest should create a MessageCreator and create a message that is sent by the producer
at least you have a more abstract approach to writing the tests, which definetively will affect how you write tests in the long run.
If you feel the need to test the behavior of your anonymous class move it outside of the publishRequest method, make it either a top level class or a static class in the class containing your publishRequest method.

Junit Test Case for Apache camel service

I created apache camel rest service to query data from DB
.get("/{id}/CodeId").description("get the CodeId").outType(String.class)
.id("CodeId").param().name("codeid").type(RestParamType.path).description("Getting Id")
.dataType("string").endParam().route()
.to("sql:select * from table1 where C_ID=:#${header.codeid} ")
.process(new Processor() {
#Override
public void process(Exchange ex) throws Exception {
String JId = null;
try {
List<HashMap> version = (List<HashMap>) ex.getIn().getBody();
if (version != null && version.size() > 0) {
LOG.debug(
"jId------------------------------>" + version.get(0).get("J_ID"));
JId = (String) version.get(0).get("J_ID");
}
ex.getIn().setBody(JId, String.class);
ex.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 201);
} catch (Exception e) {
e.printStackTrace();
}
}
}).endRest();
Actually it works fine but i was not able to write junit test cases for the service.
Can anyone please suggest me a method to write a Junit Test Case to check the values from the service ??
In fact I have documented everything around unit test cases here :
http://bushorn.com/unit-testing-apache-camel/
http://bushorn.com/camel-unit-testing-using-mock-endpoint/
In your scenario, what you have to do is, you have to replace whatever rest from endpoint in your route with a direct endpoint. That way you can send any payload from your unit test case. Its always a good practice to do these unit test cases protocol agnostic. Meaning, dont involve REST, JMS, STOMP or any external calls in your unit cases, that way you can focus to test only your routing logic. Protocol level testing you can anyway cover in integration testing.
Cheers.
You can use any http client (for example camel-http)
class RestDemoTest extends CamelTestSupport {
override def createRouteBuilder(): RouteBuilder = new RestDslRoutes()
#Test
def smokeTest(): Unit ={
val body: String = template.requestBodyAndHeader("http://localhost:9898/demo/status","",Exchange.HTTP_METHOD, "GET", classOf[String])
org.junit.Assert.assertThat(body,Is.is("Running"))
}
}
Sample code is in scala, but i'm sure you get the idea
EDIT: as per request a sample with obtaining a mock:
class RestDemoTest extends CamelTestSupport {
override def createRouteBuilder(): RouteBuilder = new RestDslRoutes()
// This example uses auto mocking endpoints based on a pattern
override def isMockEndpointsAndSkip: String = "sql:*"
#Test
def mockDemo(): Unit = {
// Obtain auto-created mock endpoint (false indicates: don't create if it does not exist yet. Helps with typos
val mockEndpoint: MockEndpoint = getMockEndpoint("mock:sql:update foo set bar=10",false)
// Set expectations/behaviour etc
mockEndpoint.expectedMessageCount(1)
val body: String = template.requestBody("http://localhost:9898/demo/update", "", classOf[String])
/// assert expectations/behaviour
mockEndpoint.assertIsSatisfied()
}

How should I mock Jersey HTTP-client requests?

This is the class I'm trying to test (it calculates the size of HTTP page):
import javax.ws.rs.core.MediaType;
import com.sun.jersey.api.client.*;
public class Loader {
private Client client;
public Loader(Client c) {
this.client = c;
}
public Integer getLength(URI uri) throws Exception {
return c.resource(uri) // returns WebResource
.accept(MediaType.APPLICATION_XML) // returns WebResource.Builder
.get(String.class) // returns String
.length();
}
}
Of course it just an example, not a real-life solution. Now I'm trying to test this class:
public class LoaderTest {
#Test public void shouldCalculateLength() throws Exception {
String mockPage = "test page"; // length is 9
Client mockedClient = /* ??? */;
Loader mockedLoader = new Loader(mockedClient);
assertEquals(
mockPage.length(),
mockedLoader.getLength(new URI("http://example.com"))
);
}
}
How should I mock com.sun.jersey.api.client.Client class? I'm trying to use Mockito, but any other framework will be OK, since I'm a newbie here..
You example is really complex, i wasnt able to run it with newest version of jersey, so i created those classes and here is how i mock it with EasyMock.
String mockPage = "test page"; // length is 9
RequestBuilder requestBuilderMock = createNiceControl().createMock(RequestBuilder.class);
expect(requestBuilderMock.get((Class < String >) anyObject())).andReturn("12345678").anyTimes();
replay(requestBuilderMock);
WebResource webResourcemock = createNiceControl().createMock(WebResource.class);
expect(webResourcemock.accept((String[]) anyObject())).andReturn(requestBuilderMock).anyTimes();
replay(webResourcemock);
Client clientMock = createNiceControl().createMock(Client.class);
expect(clientMock.resource((URI) anyObject())).andReturn(webResourcemock).anyTimes();
replay(clientMock);
Loader mockedLoader = new Loader(clientMock);
assertEquals((Integer) mockPage.length(), mockedLoader.getLength(new URI("http://example.com")));
If any of classes that you are trying to mock doesnt have default constructor then you should use
http://easymock.org/api/easymock/3.0/org/easymock/IMockBuilder.html#withConstructor%28java.lang.Class...%29
Not really related to your question, but may come in handy later, is the Jersey Test Framework. Check out these blog entries by one of the Jersey contributors;
http://blogs.oracle.com/naresh/entry/jersey_test_framework_makes_it
http://blogs.oracle.com/naresh/entry/jersey_test_framework_re_visited
Back on topic, to test your Loader class you can simply instantiate it with a Client obtained from Client.create(). If you are using Maven you can create a dummy test endpoint (in src/test/java) to call and the Jersey Test framework will load it in Jetty.

How do I create a mock object for Spring's WebServiceTemplate?

I have a class which calls out to an existing web service. My class properly handles valid results as well as fault strings generated by the web service. The basic call to the web service looks something like this (although this is simplified).
public String callWebService(final String inputXml)
{
String result = null;
try
{
StreamSource input = new StreamSource(new StringReader(inputXml));
StringWriter output = new StringWriter();
_webServiceTemplate.sendSourceAndReceiveToResult(_serviceUri, input, new StreamResult(output));
result = output.toString();
}
catch (SoapFaultClientException ex)
{
result = ex.getFaultStringOrReason();
}
return result;
}
Now I need to create some unit tests which test all of the success and failure conditions. It cannot call the actual web service, so I was hoping there were mock objects available for the client side of Spring-WS. Does anyone know of an mock objects available for the WebServiceTemplate or any related classes? Should I just attempt to write my own and modify my class to use the WebServiceOperations interface vs. WebServiceTemplate?
Michael's answer is very close, but here is the example that works.
I already use Mockito for my unit tests, so I am familiar with the library. However, unlike my previous experience with Mockito, simply mocking the return result does not help. I need to do two things to test all of the use cases:
Modify the value stored in the StreamResult.
Throw a SoapFaultClientException.
First, I needed to realize that I cannot mock WebServiceTemplate with Mockito since it is a concrete class (you need to use EasyMock if this is essential). Luckily, the call to the web service, sendSourceAndReceiveToResult, is part of the WebServiceOperations interface. This required a change to my code to expect a WebServiceOperations vs a WebServiceTemplate.
The following code supports the first use case where a result is returned in the StreamResult parameter:
private WebServiceOperations getMockWebServiceOperations(final String resultXml)
{
WebServiceOperations mockObj = Mockito.mock(WebServiceOperations.class);
doAnswer(new Answer()
{
public Object answer(InvocationOnMock invocation)
{
try
{
Object[] args = invocation.getArguments();
StreamResult result = (StreamResult)args[2];
Writer output = result.getWriter();
output.write(resultXml);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}).when(mockObj).sendSourceAndReceiveToResult(anyString(), any(StreamSource.class), any(StreamResult.class));
return mockObj;
}
The support for the second use case is similar, but requires the throwing of an exception. The following code creates a SoapFaultClientException which contains the faultString. The faultCode is used by the code I am testing which handles the web service request:
private WebServiceOperations getMockWebServiceOperations(final String faultString)
{
WebServiceOperations mockObj = Mockito.mock(WebServiceOperations.class);
SoapFault soapFault = Mockito.mock(SoapFault.class);
when(soapFault.getFaultStringOrReason()).thenReturn(faultString);
SoapBody soapBody = Mockito.mock(SoapBody.class);
when(soapBody.getFault()).thenReturn(soapFault);
SoapMessage soapMsg = Mockito.mock(SoapMessage.class);
when(soapMsg.getSoapBody()).thenReturn(soapBody);
doThrow(new SoapFaultClientException(soapMsg)).when(mockObj).sendSourceAndReceiveToResult(anyString(), any(StreamSource.class), any(StreamResult.class));
return mockObj;
}
More code may be required for both of these use cases, but they work for my purposes.
actually i don't know if there exist preconfigured Mock Objects, but i doubt there are configured for all your "failure Conditions", so you can create a special Spring ApplicationContext for your JUnit Test with a substitute or work with a mock Framework, it's not that hard :-)
i used the Mockito Mock Framework for the example (and typed it quickly), but EasyMock or your preferred mock framework should do it as well
package org.foo.bar
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
public class WebserviceTemplateMockTest {
private WhateverTheInterfaceIs webServiceTemplate;
private TestClassInterface testClass;
private final String inputXml = "bar";
#Test
public void testClient(){
//
assertTrue("foo".equals(testClass.callWebService(inputXml));
}
/**
* Create Webservice Mock.
*/
#Before
public void createMock() {
// create Mock
webServiceTemplate = mock(WhateverTheInterfaceIs.class);
// like inputXml you need to create testData for Uri etc.
// 'result' should be the needed result data to produce the
// real result of testClass.callWebService(...)
when(webServiceTemplate.sendSourceAndReceiveToResult(Uri, inputXml, new StreamResult(output))).thenReturn(result);
// or return other things, e.g.
// .thenThrow(new FoobarException());
// see mockito documentation for more possibilities
// Setup Testclass
TestClassImpl temp = new TestClassImpl();
temp.setWebServiceTemplate(generatedClient);
testClass = temp;
}
}

PowerMocking a new instantiation

In a class that I am testing with PowerMock I have the following instantiation of a class
EmailMessage msg = new EmailMessage(getExchangeSession());
EmailMessage is a third party tool that I am mocking while getExchangeSession() is a enherited protected method. I need to mock the EmailMessage but I really don't care about the call to getExchangeSession().
At the moment I have the following, but the getExchangeSession() method is still called:
#RunWith(PowerMockRunner.class)
#PrepareForTest({EmailProvider.class, ExchangeService.class})
public class MyTest {
#Test
public void test() {
EmailMessage emailMessage = createMock(EmailMessage.class);
ExchangeService exchangeService = createMock(ExchangeService.class);
expectNew(EmailMessage.class, exchangeService).andReturn(emailMessage);
// test setup and call to the class under test
Email email = new Email();
new EmailProvider().send(email);
}
}
public class EmailProvider() extends ClassWithProtectedAccess {
public void send(Email email) {
EmailMessage msg = new EmailMessage(getExchangeSession());
// and here follows the code that I am actually testing
// and which works on the msg (EmailMessage)
// ...
}
}
The first line of EmailProvider.send() is it that runs getExchangeSession() and which then fails.
So apparently I can't skip the call to getExchangeSession(), and I should probably mock this method also. Is this correct?
And if so, using PowerMock with EasyMock how can I mock this protected method?
If the class you are testing has this line in it:
EmailMessage msg = new EmailMessage(getExchangeSession());
then you can't skip the call to getExchangeSession() by powermocking the constructor of EmailMessage - it's called before the constructor is invoked, and the return value is then passed to EmailMessage (regardless of whether that is real or mocked).
So, if you can't set up your class such that the call to getExchangeSession works, you will need to mock that call as described at this question: mocking protected method.
As i understood your question correctly, your are expecting to mock EmailMessage class, but need to skip the constructor call when you create an instance.
... test setup and call to the class under test ...
Email email = new Email();
new EmailProvider().send(email);
The problem is the way you test. Your intention is to test the code in send method. you cannot just call that send() method to test. You need to write code a test the statements in send() method by mocking the dependency classes and test other statement in the class
public void testSend() throws Exception
{
// you need to suppress the constructor before you mock the class.
PowerMockito.suppress(PowerMockito.constructor(EmailMessage.class));
EmailMessage emailMessage = PowerMockito.mock(EmailMessage.class);
Email email = new Email();
emailMessage.setSubject(email.getSubject());
// ...your other code here ...
}

Resources