Mocking an autowired field using mockito gives null response in rest call - rest

I am using spring boot and mockito. I have autowired one class i.e, BDSRequest and in Junit Test class, i have used #Spy and #InjectMocks annotations. but while calling rest services in Junits, i am getting response (bdsCustomerHoldings) as null and assertion is failing. How to test this rest call with out mocking rest template like mockito.when(restTemplate.postForObject(Constants.BDS_REST_URL, bdsRequest,
BDSCustomerHoldings.class) ?
class BDSRestCall
{
#Autowired
BDSRequest bdsRequest;
public BDSCustomerHoldings getBDSCustomerInfo(String channelId, String customerId, String cinSuffix,
String countryCode) {
logger.info("prepareRequestForBDS");
Header header = new Header();
header.setMsgId(RandomStringUtils.randomAlphanumeric(20));
header.setChannelId(channelId);
header.setCountryCode(countryCode);
header.setRecordTimeStamp(DateTimeFormatter.ofPattern(Constants.DATE_FORMATTER).format(LocalDateTime.now()));
TxnRequest txnRequest = new TxnRequest();
txnRequest.setIdDoc(customerId);
txnRequest.setIdDocSuffix(cinSuffix);
txnRequest.setIdDoctype("");
txnRequest.setInsurerCode("");
bdsRequest.setHeader(header);
bdsRequest.setTxnRequest(txnRequest);
logger.info("BDS request " + bdsRequest);
BDSCustomerHoldings bdsResponse = restTemplate.postForObject(Constants.BDS_REST_URL, bdsRequest,
BDSCustomerHoldings.class);
logger.info("BDS Response : " + bdsResponse);
return bdsResponse;
}
}
Junit:
#RunWith(MockitoJUnitRunner.class)
class BDSRestCallTest
{
#InjectMocks
private BDSRestCall bdsRestCall;
#Mock
private RestTemplate restTemplate;
#Spy
private BDSRequest bdsRequest;
#Test
public void getBDSCustomerInfoExceptionTest() {
BDSCustomerHoldings bdsCustomerHoldings = bdsRestCall.getBDSCustomerInfo("SG", "S9718016D",
"00", "SG");
System.out.println("response is " + bdsCustomerHoldings);
assertNotNull("response is not null", bdsCustomerHoldings);
}
}

As we are using #RunWith(MockitoJUnitRunner.class), then we should use mocking the response of restTemplate like below
Mockito.when(restTemplate.postForObject(Mockito.anyString(), bdsRequest, BDSCustomerInsuranceHoldings.class)).thenReturn(sampleBDSCustomerInsuranceHoldings());
Then it will give mock response.

Related

Retrofit with soap api

I am trying to create Retrofit instance with the soap API. But I don't have an idea how to create. I have checked all the websites. I have got the code for creating the Retrofit instance with Rest API.
Also, I am having WSDL file. I am able to create required POJO class with that but I don't know how to use for a service call.
Kindly anyone please suggest some code or how to use that.
For Rest call, I am creating Retrofit instance like
#GET("users/{user}/repos")
Call<List<User>> listUsers(#Path("user") String user);
You should first make ApiClient class as follow:
public class ApiClient {
public static final String BASE_URL = "http://54.255.249.65/socialcommerce/rest/V1/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
In the controller class you should use the above class as follow:
ApiInterface apiInterface = ApiClientInstagram.getClient().create(ApiInterface.class);
Call<InstagramDetail> call = apiInterface.getInstagramDetail(token);
Log.d("tag", call.request().url().toString());
call.enqueue(new Callback<InstagramDetail>() {
#Override
public void onResponse(Call<InstagramDetail> call, Response<InstagramDetail> response) {
String code = String.valueOf(response.code());
if (code.equals("200")) {
response.body();
} else {
Toast.makeText(getApplicationContext(), "Backend Error", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<InstagramDetail> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});

JUnit Test cases for Rest URL

I am facing problem to write test cases for a rest url which calls another URL through Rest Template.
Please find my code below:-
#RestController
public class ParentController{
#Value("${child.url}")
private String childUrl;
#Autowired
private RestTemplateUtil restTemplateUtil;
#RequestMapping(value = "/parent",method = RequestMethod.POST)
public ResponseEntity<Object> callChildController(#RequestBody InputParam inputParam, HttpServletRequest request) {
return restTemplateUtil.templateService(restTemplateUtil.formURL(request, childUrl), HttpMethod.POST,null,inputParam, Object.class);
}}
}
#Service
public class RestTemplateUtil {
RestTemplate restTemplate = new RestTemplate();
public ResponseEntity<Object> templateService(String url, HttpMethod method, HttpHeaders headers, ...............){
logger.info("Rest template service called..");
response = restTemplate.exchange(url,method,entity,responseType);
return response;
}
public String formURL(HttpServletRequest request, String childUrl){
return "http://" + request.getServerName() + ":" + request.getServerPort() + childUrl;
}
}
JUnit Test case written:-
Mockito.when(restTemplateUtil.templateService(Mockito.anyString(),
Mockito.<HttpMethod> eq(HttpMethod.POST),
Mockito.<HttpHeaders> any(),
Mockito.<HttpEntity<?>> any(),
Mockito.<Class<Object>> any())).thenReturn(mockRespEntity);
this.mvc.perform(post("/parent")
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(requestObj)))
.andExpect(status().is2xxSuccessful());
I am a newbie to Mockito, so with my meagre knowledge have build the above test case.
Please advise and correct me if I am wrong.
On executing this, I am getting error:-
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:80/child": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
The portno is wrong here.
Please help.
Thanks.

CXF-WS integration with spring boot (jhipster stack)

I try to integrate CXF WS to jhipster stack, so avoid xml configuration.
The first class to config service
#EnableWs
#Configuration
#AutoConfigureAfter(WebConfigurer.class)
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean dispatcherServlet() {
CXFServlet cxfServlet = new CXFServlet();
return new ServletRegistrationBean(cxfServlet, "/soap/*");
}
#Bean(name = "cxf")
public SpringBus springBus() {
return new SpringBus();
}
#Bean
public Hello hello() {
return new HelloPortImpl();
}
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), hello());
endpoint.publish("/hello");
return endpoint;
}
}
The second file :
#WebService(targetNamespace = "http://service.ws.sample/", name = "Hello")
public interface Hello {
#WebResult(name = "return", targetNamespace = "")
#RequestWrapper(localName = "sayHello", targetNamespace = "http://service.ws.sample/", className = "com.orange.api.rfid.tacites.proxyauth.web.restWS.SayHello")
#WebMethod(action = "urn:SayHello")
#ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://service.ws.sample/", className = "com.orange.api.rfid.tacites.proxyauth.web.restWS.SayHelloResponse")
public java.lang.String sayHello(
#WebParam(name = "myname", targetNamespace = "")
java.lang.String myname
);
}
The third file
#javax.jws.WebService(
serviceName = "HelloService",
portName = "HelloPort",
targetNamespace = "http://service.ws.sample/",
endpointInterface = "com.orange.api.rfid.tacites.proxyauth.web.restWS.Hello")
public class HelloPortImpl implements Hello {
private static final Logger LOG = Logger.getLogger(HelloPortImpl.class.getName());
public java.lang.String sayHello(java.lang.String myname) {
LOG.info("Executing operation sayHello" + myname);
try {
return "Welcome to CXF Spring boot " + myname + "!!!";
} catch (java.lang.Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
In my logs when start spring boot, i have this line:
[DEBUG] com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator - Wrigin XML Schema for com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator#6a08fd54[http://service.ws.sample/=com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator$Namespace#76617add]
com.sun.xml.bind.v2.util.StackRecorder: null
at com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator.write(XmlSchemaGenerator.java:441) [jaxb-impl-2.2.jar:2.2]
The problem is Jhipster index.html is not found and in http://localhost:8080/soap/hello i have No binding operation info while invoking unknown method with params unknown
I think the cxf servlet kill first one servlet, how to configure to coexist both?
Regards
Try renaming your WebServiceConfig.dispatcherServlet method to something else as there is probably a bean with this name defined by Spring Boot that you're overriding.
To solve the issue, i add to WebConfigurer.java:
/**
* Initialize cxf - ws
*/
private void initCxf(ServletContext servletContext) {
log.debug("Initialize cxf - ws");
ServletRegistration.Dynamic cxfServlet = servletContext.addServlet("CxfWS", new CXFServlet());
cxfServlet.addMapping("/soap/*");
cxfServlet.setLoadOnStartup(3);
}
I've got this error when not specifying the proper wsdl name. Verify that the Soap Service instance uses a proper path to wsdl.

NoSuchMethodError: Creating rest service

I have written a JAX-RS service with following auto created interface from the wadl configuration. But I am landing into following issue. What can be the cause of this error? The service is running for single Play object, the Path params but not for ArrayOfPlay. I am able to send an ArrayOfPlay from the server to client but facing this trouble while sending from client to server.
#Path("/play")
public interface PlayService {
#POST
#Consumes({"application/xml", "application/json" })
#Produces({"application/xml", "application/json" })
#Path("/post")
Response postUpdate(ArrayOfPlay arrayofplay);
}
java.lang.NoSuchMethodError: javax.ws.rs.InternalServerErrorException.validate(Ljavax/ws/rs/core/Response;Ljavax/ws/rs/core/Response$Status;)Ljavax/ws/rs/core/Response;
at javax.ws.rs.InternalServerErrorException.<init>(InternalServerErrorException.java:126)
at org.apache.cxf.jaxrs.utils.SpecExceptions.toInternalServerErrorException(SpecExceptions.java:79)
at org.apache.cxf.jaxrs.utils.ExceptionUtils.toInternalServerErrorException(ExceptionUtils.java:106)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.convertExceptionToResponseIfPossible(JAXRSInInterceptor.java:226)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:215)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:77)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
CXF version: 3.1.0
ArrayOfPlay
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"play"
})
#XmlRootElement(name = "ArrayOfPlay")
public class ArrayOfPlay
implements Serializable
{
private final static long serialVersionUID = 1L;
#XmlElement(name = "Play", required = true)
protected List<Play> play;
public List<Play> getPlay() {
if (play == null) {
play = new ArrayList<Play>();
}
return this.play;
}
}
Update: If I send a List instead of ArrayOfPlay I am able to make it work. How to represent as List in wadl? The current representation is:
<representation mediaType="application/xml" element="ns:ArrayOfPlay"/>

Spring 4 Restfull Service with bean

I am trying to create a simple Server / Client application that can send a bean as parameter instead of String but failing below is my code
Server
#Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(method=RequestMethod.POST,value="/returnGreet")
public #ResponseBody Greeting returnGreet(
#RequestBody(required=false) Greeting greet) {
if(greet == null)
return new Greeting(counter.incrementAndGet(),
String.format(template, greet));
else
return new Greeting(0,"Testing");
}
}
Client
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,Greeting> greet = new LinkedMultiValueMap<String, Greeting>();
greet.add("greet", new Greeting(0,"XOXO"));
greeting = restTemplate.postForObject("http://localhost:8080/returnGreet",greet, Greeting.class,greet);
System.out.println("Content: " + greeting.getContent());
System.out.println("Id: " + greeting.getId() );
The result is always null for the object greet at the server side.
Any Idea ?
You're not using the RestTemplate correctly. Why are you passing a MultiValueMap as the Entity to be sent? This won't get serialized the way your Server expects.
Just use the Greeting object directly.
restTemplate.postForObject("http://localhost:8080/returnGreet", new Greeting(0, "XOXO"), Greeting.class);
Also, the last argument is not necessary, you don't have any URI variables.