HttpMediaTypeNotSupportedException on mockmvc post - unit-testing

I have a RestController and a function that accepts post requests
#RequestMapping(path = "/auth",method = RequestMethod.POST)
public void authenticate(#RequestBody AuthenticationRequest authenticationRequest, HttpServletResponse httpServletResponse) throws IOException {
}
I try to issue a post request
mockMvc.perform(post("/auth")
.contentType(MediaType.APPLICATION_JSON)
.content("{ \"foo\": \"bar\", \"fruit\": \"apple\" }".getBytes()))
.andDo(print());
I receive
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
Any workaround ideas?
Edit: I also tried specifying the consumes="application/json" on the controller, but still does not work.

The Exception says that the "media type" aka "content type" is not accepted.
Try adding consumes = "application/json" to your controller function.
#RequestMapping(path = "/auth",method = RequestMethod.POST,consumes = "application/json")
public void authenticate(#RequestBody AuthenticationRequest authenticationRequest, HttpServletResponse httpServletResponse) throws IOException {
}
See the spring documentation for details https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#consumes--

Related

Spring-Webflux: Handler function unit test is throwing UnsupportedMediaTypeStatusException

I am trying to write Unit test to the handler function, I followed the example from the Spring project. Can someone help me why the following test is throwing UnsupportedMediaTypeStatusException?
Thanks
Handler function
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
log.info("{} Processing create request", serverRequest.exchange().getLogPrefix());
return ok().body(serverRequest.bodyToMono(Person.class).map(p -> p.toBuilder().id(UUID.randomUUID().toString()).build()), Person.class);
}
Test Class
#SpringBootTest
#RunWith(SpringRunner.class)
public class MyHandlerTest {
#Autowired
private MyHandler myHandler;
private ServerResponse.Context context;
#Before
public void createContext() {
HandlerStrategies strategies = HandlerStrategies.withDefaults();
context = new ServerResponse.Context() {
#Override
public List<HttpMessageWriter<?>> messageWriters() {
return strategies.messageWriters();
}
#Override
public List<ViewResolver> viewResolvers() {
return strategies.viewResolvers();
}
};
}
#Test
public void handle() {
Gson gson = new Gson();
MockServerWebExchange exchange = MockServerWebExchange.from(
MockServerHttpRequest.post("/api/create")
.body(gson.toJson(Person.builder().firstName("Jon").lastName("Doe").build())));
MockServerHttpResponse mockResponse = exchange.getResponse();
ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
Mono<ServerResponse> serverResponseMono = myHandler.handle(serverRequest);
Mono<Void> voidMono = serverResponseMono.flatMap(response -> {
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK);
boolean condition = response instanceof EntityResponse;
assertThat(condition).isTrue();
return response.writeTo(exchange, context);
});
StepVerifier.create(voidMono)
.expectComplete().verify();
StepVerifier.create(mockResponse.getBody())
.consumeNextWith(a -> System.out.println(a))
.expectComplete().verify();
assertThat(mockResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
}
}
Error Message:
java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onError(org.springframework.web.server.UnsupportedMediaTypeStatusException: 415 UNSUPPORTED_MEDIA_TYPE "Content type 'application/octet-stream' not supported for bodyType=com.example.demo.Person"))
I found that I missed .contentType(MediaType.APPLICATION_JSON) to my mock request.
MockServerWebExchange.from(
MockServerHttpRequest.post("/api/create").contentType(MediaType.APPLICATION_JSON)
.body(gson.toJson(Person.builder().firstName("Jon").lastName("Doe").build())));
fixed my issue.

Spring boot How to access Appconfig properties in test case

I am new to web services and spring boot. I have written a service for which I am now writing a test case.
My application gets Soap request, parses the body and saves contents into database.
My test case tests this service.
When I run the application and send a request from Postman, it runs alright. But when I call my service method from test case, I get nullpointer for JaxBcontext.
I have declared Jaxbcontext in my AppConfig.java (which is annotated with #Configuration and my jaxb is a bean with #Bean annotation) in my service, I have #autowire to use jaxbcontext.
I have pasted code snippets for clarity. Please advise me what I am doing wrongly here.
My test case
public class ReferralExchangeEndpointTest {
ReferralExchangeEndpoint referralExchangeEndpoint = new ReferralExchangeEndpoint();
JAXBContext jbcTest;
Marshaller marshaller;
Unmarshaller unmarshaller;
public ReferralExchangeEndpointTest() throws JAXBException {
}
#Before
public void setUp() throws Exception {
jbcTest = JAXBContext.newInstance(
"our app schema"); // this is working fine, I have replaced schema with this text for posting it in stack.
ObjectFactory factory = new ObjectFactory();
marshaller = jbcTest.createMarshaller();
unmarshaller = jbcTest.createUnmarshaller();
}
#Test
public void send() throws Exception {
File payload = new File("payload.xml");
Object x = unmarshaller.unmarshal(payload);
JAXBElement jbe = (JAXBElement) x;
System.out.println(jbe.getName());
Object test = jbe.getValue();
SendRequestMessage sendRequestMessage = (SendRequestMessage) jbe.getValue();
// Method in test.
referralExchangeEndpoint.send(sendRequestMessage);
}
}
My service class
#Endpoint
public class ReferralExchangeEndpoint {
public static final Logger logger = LoggerFactory.getLogger(ReferralExchangeEndpoint.class);
#Autowired
private JAXBContext jaxbContext;
#Autowired
.
.
.
private Form parseBody(String payLoadBody) {
try {
Unmarshaller um = jaxbContext.createUnmarshaller();
return (Form) um.unmarshal(new StringReader(payLoadBody));
} catch (Exception e) {
throw new RuntimeException("Failed to extract the form from the payload body", e);
}
}
My appconfig file
#Configuration
public class AppConfig {
#Bean
public JAXBContext jaxbContext() throws JAXBException {
return
JAXBContext.newInstance("packagename");
}
#Bean public MessagingService messagingService() {
return new MessagingService();
}
}
Thanks.
Kavitha.
** Solved **
My test case now looks like this.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {AppConfig.class})`
public class ReferralExchangeEndpointTest {
#Autowired
ReferralExchangeEndpoint referralExchangeEndpoint;
#Autowired
private JAXBContext jaxbContext;
private Marshaller marshaller;
private Unmarshaller unmarshaller;
#Before
public void setUp() throws Exception {
marshaller = jaxbContext.createMarshaller();
unmarshaller = jaxbContext.createUnmarshaller();
}
#Test
public void send() throws Exception {
File payload = new File("src/test/resources/payload.xml");
JAXBElement jbe = (JAXBElement) unmarshaller.unmarshal(payload);
SendRequestMessage sendRequestMessage = (SendRequestMessage) jbe.getValue();
JAXBElement<SendResponseMessage> response = referralExchangeEndpoint.send(sendRequestMessage);
//TODO add remaining assertions on response after confirming what should the service return for these attributes.
assertEquals("SiteId wrong in response: ", "siteId", response.getValue().getSiteId());
}
}`

Retrofit 2.1 Internal Server Error with Post

I am using Retrofit 2.1 and when i am posting an object to my server, it gives me Internal server error with status code = 500, but i try to to post from my backend, it works like a charm, I am sure this is not server's problem.
Undoubtedly, i should use retrofit as a singleton:
//return api if not null
HereApi getApi(){
if (api == null) {
api = getRetrofit().create(HereApi.class);
}
return api;
}
//returns restadapter if not null
Retrofit getRetrofit(){
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("my endpoint")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
and this method that i post Here object:
void createHere(Here here){
List<Here> list = new ArrayList<>();
list.add(here);
Call<List<Here>> call = getApi().createHere(list);
call.enqueue(new Callback<List<Here>>() {
#Override
public void onResponse(Call<List<Here>> call, Response<List<Here>> response) {
Log.i(TAG, "onResponse: "+response.message());
}
#Override
public void onFailure(Call<List<Here>> call, Throwable t) {
}
});
}
I tried to post a list with single object inside and to post one object alone, but still status code is 500 ;*(
This is my api service interface:
public interface HereApi{
#GET("/lessons/")
Call<List<Lesson>> getLesson(#QueryMap Map<String,String> map);
#Headers({
"Content-Type: application/json",
"Vary: Accept"
})
#POST("/heres/")
Call<List<Here>> createHere(#Body List<Here> list);
#GET("/heres/")
Call<List<Here>> getHeres(#QueryMap Map<String,String> map);
}
I have written backend in Django + Django-rest-framework:
When I try to post from this, it just works:
I need your help guys, i have only one day to complete this project!!!
Hi I think there is a datetime conversation issue.
Use Jackson formating attonation in order to properly serialize datetime field.

spring mvc controller test org.springframework.web.HttpMediaTypeNotSupportedException

Can someone help on this?
I am getting the below exception(org.springframework.web.HttpMediaTypeNotSupportedException) when I run this test.
In the response I get this Headers.
Headers = {Accept=[application/octet-stream, text/plain;charset=ISO-8859-1, application/xml, text/xml, application/x-www-form-urlencoded, application/+xml, multipart/form-data, application/json;charset=UTF-8, application/+json;charset=UTF-8, /]}
The add method in the controller is
#RequestMapping(value = "/addTrain", method = RequestMethod.POST)
public #ResponseBody void addTrain(#RequestBody Train train) {
trainService.addTrain(train);
}
I am doing JUnit test for a method. Below is my Test class and MockHttpServletRequest and MockHttpSErvletResponse.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/config/webapp-config.xml" })
#WebAppConfiguration
public class TrainControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#InjectMocks
TrainController trainController;
#Mock
private TrainService trainService;
private final List<Train> trainList = new ArrayList<Train>();
private Train train;
#Before
public void setUp() throws Exception {
// Process mock annotations
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
train = new Train();
train.setId(12L);
train.setName("chennai");
train.setSpeed(100);
train.setDiesel(true);
Train train1 = new Train();
train1.setId(15L);
train1.setName("kovai");
train1.setSpeed(150);
train1.setDiesel(false);
trainList.add(train);
trainList.add(train1);
}
#Test
public void testAddTrainList() throws Exception {
Mockito.doNothing().when(trainService).addTrain(train);
this.mockMvc.perform(post("/trains/addTrain")).andDo(print()).andExpect(status().isOk());
}
}
The request and reponse are below:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /trains/addTrain
Parameters = {}
Headers = {}
Handler:
Type = com.xvitcoder.angualrspringapp.controller.TrainController
Method = public void com.xvitcoder.angualrspringapp.controller.TrainController.addTrain(com.xvitcoder.angualrspringapp.beans.Train)
Async:
Was async started = false
Async result = null
**Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException**
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
**MockHttpServletResponse:
Status = 415
Error message = null**
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Your request has to specify the Content-type header from one of the acceptable ones.
Try changing your mock request as below:
this.mockMvc.perform(post("/trains/addTrain").contentType(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk());
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException

display pdf / download pdf from Oracle databse using spring and hibernate

I have an object with field
#Column(name = "PDF")
#Lob #Basic(fetch=javax.persistence.FetchType.LAZY)
private byte[] pdf;
My dao retrieves this object succesfully using the enitity manager findbyid() method.
I want to display this pdf on browser or download the pdf when the request comes to my controller.
This is what i did.
#Autowired
DocDownloadService docService;
HttpServletResponse response;
#RequestMapping("/document/view/{docID}")
public String getAlert(#PathVariable("docID") String docId){
docService.downloadDoc(docId, response);
return null;
}
And my service
#Override
#Transactional
public String downloadDoc(String docId, HttpServletResponse response){
MyDoc doc = this.getDocById(docId); //brings document object from my DAO
try {
response.addHeader("Content-Disposition", "attachment;filename=report.pdf");
response.setContentType("application/pdf");
response.getOutputStream().write(doc.getPdf(), 0, doc.getPdf().length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
I get a null pointer exception at the "response.addheaders line.. I am not sure why. I have looked through other posts and tried all those methods but it didnt help.
Any pointers will be appreciated.
Try this
#RequestMapping("/document/view/{docID}")
public String getAlert(#PathVariable("docID") String docId, HttpServletResponse response){
Also, it is better if you handle the response.outputstream within the controller rather than handling it at the service.