I have the following mocked server:
mockInteractiveServer = MockRestServiceServer.createServer(oauthClientConfig.getRestTemplate());
I use this mocked server in a JUnit test case:
#Test
public void myTestMethod() throws Exception{
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Location", "samplePrefix/sampleTicketId");
mockInteractiveServer
.expect(ExpectedCount.once(), requestTo(new URI("mockURI")))
.andExpect(method(HttpMethod.POST))
.andExpect(content().string("validation content"))
.andRespond(withStatus(HttpStatus.OK)
.headers(responseHeaders));
//calls the actual service, which should call the mocked server
String ticketId = interactiveTicketService.myMethod(new createTicketRequest());
assertThat(ticketId).isEqualTo("sampleTicketId");
}
The actual service, InteractiveTicketService, calls the server here:
public String myMethod(CreateTicketRequest createTicketRequest){
//This builds the model object
TicketRequest request = myBuilder.buildTicketRequest();
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
//createTicketResponse is null
ResponseEntity<String> createTicketResponse = iDOCClient.getRestTemplate()
.postForEntity(iDOCClient.getRequestUrl() + "/interactive-documents", request, String.class);
}
And this is the model class I am passing to the postForEntity() method:
public class MyTicket implements TicketRequest {
private List<Document> documents;
private PublishingRequestWrapper data;
private String assignedTo;
private String requestType;
private String templateGroup;
private List<Object> templates;
//constructors, getters & setters
}
Again, the issue I am facing is that the ResponseEntity is always null.
Related
I am new to Spring boot and sorry in case it's very basic but I am posting as I have tried other ways and checked similar threads as well.
If I use below code it's returning correct response
ResponseEntity<String> responseEntityString = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
Output
[{"Id":"123aa","TenId":5198,"Name":"test","Description":"test11","Tags":[]}]
Now I have created workspace class like below (getter/setter/arg constructor and no-arg construcntor is also there)
public class Workspace {
private String Id;
private String TenId;
private String Name;
private String Description;
private List<String> Tags;
}
Now I execute the below code -
ResponseEntity<List<Workspace>> response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
new ParameterizedTypeReference<List<Workspace>>(){});
List<Workspace> employees = response.getBody();
employees.stream().forEach(entry -> System.out.println(entry.getId() + ": " + entry.getName()));
It's returning
null: null
Below is returning true
System.out.println("Value "+ response.hasBody());
Below is returning - New Values [com.pratik.model.Workspace#3cbf1ba4]
New Values [com.pratik.model.Workspace#3cbf1ba4]
So please advise what needs to change to get the values
================================================================
Initialized resttemplate bean like below
public class app1 {
static RestTemplate restTemplate = new RestTemplate();
static String url = url;
public static void main(String[] args) {
SpringApplication.run(app1.class, args);
getCallSample();
}
===============================================================
Update on the latest code
ResponseEntity<Workspace[]> responseNew = restTemplate
.exchange(
url,
HttpMethod.GET,
requestEntity,
Workspace[].class);
Workspace [] employees1 = responseNew.getBody();
List<Workspace> list = Arrays.asList(employees1);
list.stream().forEach(entry -> System.out.println(entry.getId() + ": " + entry.getName()));
Still the response is
null: null
===============================================================
Another update
When tried with String.class it's returning
[{"Id":"abc","TenId":11,"Name":"tt1 Workspace","Description":"testtenant Workspace (System Generated)","Tags":[]}]
But when using workspace class - it's returning -
[Id=null, TenId=null, Name=null, Description=null, Tags=null, getId()=null, getTenId()=null, getName()=null, getDescription()=null, getTags()=null]
So is using Workspace[].class would be the right method ?
Replace your static RestTemplate restTemplate = new RestTemplate(); variable for a real bean:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
#Configuration
public class app1 {
//remove this variable
//static RestTemplate restTemplate = new RestTemplate();
static String url = "your_url";
public static void main(String[] args) {
SpringApplication.run(app1.class, args);
//getCallSample();
}
//create a proper RestTemplate bean
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//add a converter so you can unmarshall the json content
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
//this is an example to set an ObjectMapper instance
//you can define a bean to configure the ObjectMapper
//with specific details like avoid unmarshalling unknown fields
converter.setObjectMapper(new ObjectMapper());
restTemplate.getMessageConverters().add(converter);
return restTemplate;
}
}
Now, in the method you're using the rest template. Get it from Spring's application context rather than using your own static bean. Example:
#Component
public class WorkspaceService {
private final RestTemplate restTemplate;
public WorkspaceService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public List<Workspace> getWorkspaces() {
ResponseEntity<List<Workspace>> response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
new ParameterizedTypeReference<List<Workspace>>(){});
List<Workspace> employees = response.getBody();
employees.stream().forEach(entry -> System.out.println(entry.getId() + ": " + entry.getName()));
return employees;
}
}
Now you can use this bean in your components. For example, if you want to use it in main class:
#Configuration
public class app1 {
static String url = "your_url";
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(app1.class, args);
WorkspaceService ws = ctx.getBean(WorkspaceService.class);
ws.getWorkspaces();
}
//create a proper bean
#Bean
public RestTemplate restTemplate() {
/* code from above... */
}
}
The issue is resolved by changing the Pojo class (used this to get the class https://json2csharp.com/code-converters/json-to-pojo) to
public class Root{
#JsonProperty("Id")
public String id;
#JsonProperty("TenantId")
public int tenantId;
#JsonProperty("Name")
public String name;
#JsonProperty("Description")
public String description;
#JsonProperty("Tags")
public ArrayList<Object> tags;
}
and the code is used
ResponseEntity<Workspace[]> responseNew = restTemplate
.exchange(
url,
HttpMethod.GET,
requestEntity,
Workspace[].class);
Workspace [] employees1 = responseNew.getBody();
list.stream().forEach(entry -> System.out.println(entry.getDescription()+": "+ entry.getId() + ": " + entry.getName()));
Thanks for the responses , got to learn a lot from the answers
I have a spring boot application that makes an API hit of other internal projects using the rest template which works fine and I am writing unit test cases for it but test case if failing due to Unexpected exception thrown: java.lang.NullPointerException: Cannot invoke "org.springframework.http.ResponseEntity.getBody()" because "response" is null
Service
#Service
#Slf4j
public class DynamoDBServiceImpl implements DynamoDBService {
private final RestTemplate restTemplate;
private final HttpHeaders httpHeaders;
private final String jwtHeader;
private final String apiKeyHeader;
private final String dynamodbSysApiKey;
private final String fetchAdminGroupUrl;
public DynamoDBServiceImpl(
RestTemplate restTemplate,
HttpHeaders httpHeaders,
#Value("${header-name.jwt}") String jwtHeader,
#Value("${header-name.api-key}") String apiKeyHeader,
#Value("${dynamodb-sys-api-key}") String dynamodbSysApiKey,
#Value("${dynamodb-fetch-admin-group-url}") String fetchAdminGroupUrl) {
this.restTemplate = restTemplate;
this.httpHeaders = httpHeaders;
this.jwtHeader = jwtHeader;
this.apiKeyHeader = apiKeyHeader;
this.dynamodbSysApiKey = dynamodbSysApiKey;
this.fetchAdminGroupUrl = fetchAdminGroupUrl;
}
#Override
public List<AdminGroupDTO> getAllAdminGroups() {
log.debug("Request to get admin group details with url : {}", fetchAdminGroupUrl);
httpHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setBearerAuth(CommonUtils.getHeaderFromCurrentHttpRequest(jwtHeader));
httpHeaders.set(apiKeyHeader, dynamodbSysApiKey);
HttpEntity<AdminGroupDTO> request = new HttpEntity<>(httpHeaders);
ResponseEntity<List<AdminGroupDTO>> response =
restTemplate.exchange(fetchAdminGroupUrl, HttpMethod.GET, request, new ParameterizedTypeReference<List<AdminGroupDTO>>() {});
return response.getBody();
}
}
Test
#SpringBootTest(classes = Application.class)
public class DynamoDBServiceTest {
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private final HttpHeaders httpHeaders = new HttpHeaders();
private final DynamoDBServiceImpl dynamoDBService =
new DynamoDBServiceImpl(
restTemplate, httpHeaders, "Authorization" , "Api-Key", "fake", "https://fake.com");
#Test
void testGetAllAdminGroups() {
List<AdminGroupDTO> adminGroupDTOList = new ArrayList<>();
AdminGroupDTO adminGroupDTO = new AdminGroupDTO();
adminGroupDTO.setAdminGroupId(1L);
adminGroupDTO.setAdminGroupName("fake");
adminGroupDTO.setCountryName("fake");
adminGroupDTOList.add(adminGroupDTO);
ResponseEntity<List<AdminGroupDTO>> responseEntity = new ResponseEntity<>(adminGroupDTOList, HttpStatus.OK);
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<List<AdminGroupDTO>>>any()))
.thenReturn(responseEntity);
assertDoesNotThrow(dynamoDBService::getAllAdminGroups);
}
}
Replace this line of code :
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<List<AdminGroupDTO>>>any()))
.thenReturn(responseEntity);
With this :
when(restTemplate.exchange(
ArgumentMatchers.anyString(),
ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.any(),
ArgumentMatchers.eq(new ParameterizedTypeReference<List<AdminGroupDTO>>() {}))
)
.thenReturn(responseEntity);
And excepption should dissapear.
For futher details you can check this post.
I am new to JUNIT and using RestTemplate to call my service, I'm getting 200 response for the same. But, I can't test the class using JUnit. Tried different approaches and getting 400 and 404. I want to post the request body (json) and test the status. Please let me know if there is any issue.
/**
* Rest client implementation
**/
public class CreateEmailDelegate implements CDM {
#Autowired
private RestTemplate restTemplate;
private String url = "http://example.com/communications/emails";
public ResponseEntity<CDResponse> createEmail(CDMEmailRequest cDRequest) throws UnavailableServiceException, InvalidInputException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("SR_API_Key", SR_API_KEY);
httpHeaders.set("consumerIdentification", CONSUMER_IDENTIFICATION);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity< CDMEmailRequest > cDRequestEntity = new HttpEntity<>( cDRequest, httpHeaders);
ResponseEntity< CDResponse > cDResponse = null;
try {
cDResponse = restTemplate.postForEntity(url, cDRequestEntity, CDResponse.class);
} catch (Exception e) {
LOGGER.error(e.getMessage());
throw e;
}
return cDResponse;
}
}
My Test class which return 404 status instead of 200
#RunWith(SpringJUnit4ClassRunner.class)
public class CreateEmailCommunicationDelegateTest {
#Before
public void setup() {
httpHeaders = new HttpHeaders();
httpHeaders.set("SR_API_Key", SR_API_KEY);
httpHeaders.set("consumerIdentification", CONSUMER_IDENTIFICATION);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
this.mockMvc = builder.build();
}
public void testResponse() throws Exception, HttpClientErrorException, JsonProcessingException {
String url = "http://example.com/CommunicationDeliveryManagement-Service-1.0.0/communications/emails";
CDMEmailRequest anObject = new CDMEmailRequest();
ResultMatcher ok = MockMvcResultMatchers.status().isOk();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
String requestJson = ow.writeValueAsString(anObject);
System.out.println(requestJson);
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(url).contentType(MediaType.APPLICATION_JSON_UTF8).content(requestJson);
this.mockMvc.perform(builder).andExpect(ok).andDo(MockMvcResultHandlers.print());
}
}
My Test class using TestRestTemplate instead MockMvc returns 400
#RunWith(SpringJUnit4ClassRunner.class)
public class CreateEmailCommunicationDelegateTest {
#Before
public void setup() {
httpHeaders = new HttpHeaders();
// rest headers as above
}
#Test
public void testResponse() throws Exception, HttpClientErrorException, JsonProcessingException {
String url = "http://example.com/CommunicationDeliveryManagement-Service-1.0.0/communications/emails";
String username = "";
String password = "";
HttpEntity<CDMEmailRequest>
cDEntity = new HttpEntity<>(httpHeaders);
restTemplate = new TestRestTemplate(username, password);
responseEntity =
restTemplate.exchange(url, HttpMethod.POST, cDEntity,
CDResponse.class);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK,
responseEntity.getStatusCode());
}
}
I think you're trying to implement an integration test instead of an unit test, there is quite difference. MockMvc should be used to implement unit tests and TestRestTemplate for integration tests. You can't neither use it for testing a Client implementation.
See Unit and Integration Tests in Spring Boot
If you are working with Spring Boot you could achieve your goal using another approach see this question Spring boot testing of a rest client using #RestClientTest.
I have a rest service written using Spring Boot as below:
#RestController
class MyBankingController{
#GetMapping("/getCards")
public SomePOJO getCards(){}
#GetMapping("/cardPresent")
public boolean isCardPresent(#RequestParam(value = "username") String
username){
//calls service layer to return primitive true or false
}
}
Below is my test class:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyBankingApplication.class, webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyBankingControllerIT {
private MyBankingController myBankingController;
private TestRestTemplate restTemplate;
private static final String BASE_URL = "/company/cards";
HttpHeaders headers = new HttpHeaders();
String username = "1234";
#Autowired
private MyBankingService myBankingService;
#LocalServerPort
private int port;
#Before
public void setUp() throws Exception {
myBankingController = new MyBankingController(myBankingService);
restTemplate = new TestRestTemplate();
}
#Test
public void testIsCardPresent() throws JSONException {
String url = BASE_URL+"cardPresent?username="+username;
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<Boolean> response = restTemplate.exchange(
createURLWithPort(url),
HttpMethod.GET, entity, Boolean.class);
assertTrue(response.getBody());
}
private String createURLWithPort(String uri) {
return "http://localhost:" + port + uri;
}
}
I am unable to test this boolean return type. I have tried a couple of different things but it doesn't work. I am getting the below error.
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.lang.Boolean out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.lang.Boolean out of START_OBJECT token at [Source: (PushbackInputStream); line: 1, column: 1]
Please note that the above code is just a customized version of the actual code and that at the moment it is not possible to change the return type or the controller.
Could you be able to tell me how to test this?
Change the response type to String as sketched below, and test for "true" "false" and it should work:
ResponseEntity<String> response = restTemplate.exchange(
createURLWithPort(url),
HttpMethod.GET, entity, String.class);
I am developing a front end application using Java Spring-MVC, however I'm facing difficulties in creating Request Object for Hitting Web-Services as I did in .Net-MVC. Can anyone tell me the equivalent classes and methods in Java for below given code.
I need to replicate these 2 methods from .Net-MVC to Java.
1st Method:
private HttpWebRequest RequestObj { get; set; }
public Stream DataStreamObj { get; set; }
private RequestModel RequestModelObj { get; set;
public RequestGenerator(String WebserviceUrl)
{
RequestObj = (HttpWebRequest)WebRequest.Create(WebConfigurationManager.AppSettings["WebServiceURL"] + WebserviceUrl);
RequestObj.Method = "POST";GenerateLoginRequest
RequestObj.ContentType = "application/json";
RequestModelObj = new RequestModel();
RequestModelObj.ApiKey = WebConfigurationManager.AppSettings["apiKey"];
RequestModelObj.DeviceId = Constant.AppConstants.ONE;
}
2nd Method:
private string CallWebservice(Dictionary<String, Object> RequestDict)
{
try
{
HttpWebRequest Request = (HttpWebRequest)RequestDict["request"];
RequestModel RequestModel = (RequestModel)RequestDict["requestData"];
//Tell them the length of content
string Json = JsonConvert.SerializeObject(RequestModel);
byte[] ByteArray = Encoding.UTF8.GetBytes(Json);
Request.ContentLength = ByteArray.Length;
//Write content on stream
Stream DataStream = Request.GetRequestStream();
DataStream.Write(ByteArray, 0, ByteArray.Length);
DataStream.Close();
//Initiate Call
HttpWebResponse Response = GetWebResponse(Request);
DataStream = Response.GetResponseStream();
StreamReader Reader = new StreamReader(DataStream);
// Read the content.
string responseFromServer = Reader.ReadToEnd();
// Display the content.
Reader.Close();
Response.Close();
return responseFromServer;
}
catch (System.Net.WebException ex)
{
var response = ex.Response as HttpWebResponse;
return "";
}
}
RestTemplate class is designed to call REST services, it should come as no surprise that its main methods are closely tied to REST’s underpinnings, which are the HTTP protocol’s methods: HEAD, GET, POST, PUT, DELETE, and OPTIONS. E.g. it’s methods are headForHeaders(), getForObject(), postForObject(), put() and delete() etc.
Read More and Source Code : Spring REST JSON Example
HTTP GET Method Example
1) Get XML representation of employees collection in String format
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public String getAllEmployeesXML(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "xmlTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri =
"http://localhost:8080/springrestexample/employees.xml";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
2) Get JSON representation of employees collection in String format
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String getAllEmployeesJSON(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "jsonTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri =
"http://localhost:8080/springrestexample/employees.json";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
3) Using custom HTTP Headers with RestTemplate
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String getAllEmployeesJSON(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "jsonTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters",
headers);
ResponseEntity<String> result = restTemplate.exchange(uri,
HttpMethod.GET, entity, String.class);
System.out.println(result);
}
4) Get data as mapped object
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public String getAllEmployeesXML(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "xmlTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
EmployeeListVO result = restTemplate.getForObject(uri,
EmployeeListVO.class);
System.out.println(result);
}
5) Passing parameters in URL
REST API Code
#RequestMapping(value = "/employees/{id}")
public ResponseEntity<EmployeeVO> getEmployeeById (#PathVariable("id")
int id)
{
if (id <= 3) {
EmployeeVO employee = new
EmployeeVO(1,"Lokesh","Gupta","howtodoinjava#gmail.com");
return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
REST Client Code
private static void getEmployeeById()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1");
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.getForObject(uri, EmployeeVO.class,
params);
System.out.println(result);
}
HTTP POST Method Example
REST API Code
#RequestMapping(value = "/employees", method = RequestMethod.POST)
public ResponseEntity<String> createEmployee(#RequestBody EmployeeVO
employee)
{
System.out.println(employee);
return new ResponseEntity(HttpStatus.CREATED);
}
REST Client Code
private static void createEmployee()
{
final String uri = "http://localhost:8080/springrestexample/employees";
EmployeeVO newEmployee = new EmployeeVO(-1, "Adam", "Gilly",
"test#email.com");
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.postForObject( uri, newEmployee,
EmployeeVO.class);
System.out.println(result);
}
HTTP PUT Method Example
REST API Code
#RequestMapping(value = "/employees/{id}", method = RequestMethod.PUT)
public ResponseEntity<EmployeeVO> updateEmployee(#PathVariable("id")
int id, #RequestBody EmployeeVO employee)
{
System.out.println(id);
System.out.println(employee);
return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
}
REST Client Code
private static void deleteEmployee()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "2");
EmployeeVO updatedEmployee = new EmployeeVO(2, "New Name", "Gilly",
"test#email.com");
RestTemplate restTemplate = new RestTemplate();
restTemplate.put ( uri, updatedEmployee, params);
}
HTTP DELETE Method Example
REST API Code
#RequestMapping(value = "/employees/{id}", method =
RequestMethod.DELETE)
public ResponseEntity<String> updateEmployee(#PathVariable("id") int
id)
{
System.out.println(id);
return new ResponseEntity(HttpStatus.OK);
}
REST Client Code
private static void deleteEmployee()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "2");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete ( uri, params );
}