mockMVC method GET java.lang.AssertionError: Status Expected :200 Actual :500 - spring

i written a test in spring mockMVC this method:
my method testing is:
#Test
public void getAccount()throws Exception {
mockMvc.perform(get("/account/1"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("/account/"));
}
and i have a following bug:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /users/1
Parameters = {}
Headers = {}
Body = <no character encoding set>
Session Attrs = {}
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 500
Error message = null
Headers = {Content-Type=[text/plain;charset=ISO-8859-1], Content-Length=[14]}
Content type = text/plain;charset=ISO-8859-1
Body = We are doomed.
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :500
This is my POST method test:
what is bad in my test method? what i can fixed this?
I am asking for help and quick answer

It appears you're not looking at the right place for the issue.
The logger outputs that you have an error with the request URI /users/1:
Request URI = /users/1
and your testing method is trying to get /account/1:
mockMvc.perform(get("/account/1"))
As for the error itself, MethodArgumentTypeMismatchException:
Exception that indicates that a method argument has not the expected type.
In other words, the method which is annotated by #GetMapping("/users/{id}") has the wrong #PathVariable parameter type.
In your case, you're using UUID as parameter:
public #ResponseBody ResponseEntity<AccountDTO> getAccount(#PathVariable UUID id) {
However, in your test, you're not passing a UUID, you're passing a numerical value (long/int) in your test.
If you want to generate a random UUID, you can use UUID.randomUUID():
#Test
public void getAccount()throws Exception {
mockMvc.perform(get("/account/" + UUID.randomUUID()))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("/account/"));
}
Alternatively, you could use long instead of uuid in your mapping method:
#GetMapping(value = "/{id}")
#ApiOperation(value = "Retrieve account.")
public #ResponseBody ResponseEntity<AccountDTO> getAccount(#PathVariable Long id) {
return accountService.retreiveById(id).map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
though in that case, you'll probably have to change your AccountService.retrieveById(id) method.
Good luck!

Related

MockMvc result returns null for GET request in Spring Boot

I have a problem with testing my Spring Boot Controller. I'm trying to test one of Controller put methods, but all I'm getting is Status expected:<200> but was:<400> error message.
My Controller:
#PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateFields(#RequestBody List<UpdateModel> model) throws JsonProcessingException {
return new ResponseEntity<>(vaultService.updateFields(model), HttpStatus.OK);
}
My ControllerTest:
The URL is ok, and I have a list just like in the get method in my controller.
#Test
void updateFieldsTest() throws Exception {
List<UpdateModel> response = new ArrayList<>();
UpdateModel updateModel = new UpdateModel();
response.add(updateModel);
when(vaultService.updateFields(anyList()))
.thenReturn(String.valueOf(response));
mockMvc.perform(
MockMvcRequestBuilders.put("/api/update")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept("application/json"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
And here's an error message:
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /api/update
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json"]
Body = null
Session Attrs = {}
Handler:
Type = hr.ogcs.ltt.api.lttapi.controller.LttController
Method = hr.ogcs.ltt.api.lttapi.controller.LttController#updateFields(List)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Status expected:<200> but was:<400>
Expected :200
Actual :400
<Click to see difference>
java.lang.AssertionError: Status expected:<200> but was:<400>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:627)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:212)
at hr.ogcs.ltt.api.apicontroller.ControllerTest.updateFieldsTest(ControllerTest.java:113) <31 internal lines>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)<9 internal lines>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)<48 internal lines>
I guess it has to be something with sending the required parameter, but I'm not sure what exactly causes this 400 error.
For anyone interested, I've managed to find a solution, so here it is.
#Test
#DisplayName("Test updateFieldsTest")
void updateFieldsTest() throws Exception {
List<UpdateModel> response = new ArrayList<>();
UpdateModel updateModel = new UpdateModel();
response.add(updateModel);
when(vaultService.updateFields(anyList()))
.thenReturn(String.valueOf(response));
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(response);
mockMvc.perform(
MockMvcRequestBuilders.put("/api/update")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(json)
.accept("application/json"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
If you compare this code with the one in my original post, the difference is in adding the ObjectMapper.
You do not have content in the request
mockMvc.perform(
MockMvcRequestBuilders.put("/api/update")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonString)
.accept("application/json"))
.andExpect(MockMvcResultMatchers.status().isOk());
}

Junit rest controller throws login url instead of Actual model and view

I am tring to test my spring-boot rest controller, its giving the login page instead of actual result. its giving 302 status, I have given the controller code , test case and error given by the junit.Please have look all the code and let me you need any other information
Controller
#GetMapping("{userId}/edit/{todoId}")
public ModelAndView updateTodo(#PathVariable Long userId, #PathVariable Long todoId) {
User user = userService.findById(userId);
ModelAndView model = new ModelAndView("todo-form.jsp");
model.addObject("userId",userId);
return model;
}
Junit test
#ExtendWith(SpringExtension.class)
#SpringBootTest
#AutoConfigureMockMvc
class UserApiControllerTest {
#DisplayName("Test updateTodo Api")
#Test
public void updateTodo() throws Exception {
mockMvc.perform(get("/1/edit/2"))
.andExpect(status().isOk());
}
ERROR
MockHttpServletRequest:
HTTP Method = GET
Request URI = /1/edit/2
Parameters = {}
Headers = []
Body = null
Session Attrs = {SPRING_SECURITY_SAVED_REQUEST=DefaultSavedRequest[http://localhost/1/edit/2]}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 302
Error message = null
Expires:"0", Location:"http://localhost/login"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = http://localhost/login
Try disabling spring security as it's redirecting to login page.
#AutoConfigureMockMvc(addFilters = false)
secure=false should work too but may be deprecated depending on your version of Spring

"Could not find acceptable representation" when testing spring download link with MockMvc

I have a controller that should allow downloading files with arbitrary content type:
#GetMapping(value="/download/{directory}/{name}",
consumes=MediaType.ALL_VALUE)
#Timed
public ResponseEntity<byte[]> downloadFile(#PathVariable String directory,
#PathVariable String name) {
log.debug("REST request to download File : {}/{}", directory, name);
byte[] content = "it works".getBytes();
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
return new ResponseEntity<>(content, headers, HttpStatus.OK);
}
I want to test that in a unit test like this:
...
private MockMvc restFileMockMvc;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
final FileResource fileResource = new FileResource(fileService);
this.restFileMockMvc = MockMvcBuilders.standaloneSetup(fileResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService())
.setMessageConverters(jacksonMessageConverter)
.setValidator(validator).build();
}
#Test
#Transactional
public void downloadFile() throws Exception {
String url = "/api/download/it/works.txt";
restFileMockMvc.perform(get(url).header(HttpHeaders.ACCEPT, "*/*"))
.andDo(MockMvcResultHandlers.print()) // Debugging only!
.andExpect(status().isOk());
}
But obviously, there is a problem with the content type, resp. the accept header. MockMvcResultHandlers.print() produces the following:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/download/DIRDIR/NAMENAME
Parameters = {}
Headers = {Accept=[*/*]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.example.storage.web.rest.FileResource
Method = public org.springframework.http.ResponseEntity<byte[]> com.example.storage.web.rest.FileResource.downloadFile(java.lang.String,java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotAcceptableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 406
Error message = null
Headers = {Content-Type=[application/problem+json]}
Content type = application/problem+json
Body = {"type":"https://www.jhipster.tech/problem/problem-with-message","title":"Not Acceptable","status":406,"detail":"Could not find acceptable representation","path":"/api/download/DIRDIR/NAMENAME","message":"error.http.406"}
Forwarded URL = null
Redirected URL = null
Cookies = []
It looks like the request is sent with Accept: */*. What does Spring complain about then?
It could be an issue with your message converter, used in your test case. I too faced similar issue and resolved it by passing additional parameter in messageConverter for my mockMvc
this.restMockMvc = MockMvcBuilders.standaloneSetup(testResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setMessageConverters(jacksonMessageConverter,new
ByteArrayHttpMessageConverter()).build();
You need to overload message converter property for MockMVC. for more info , relevant question
I was already using #SpringJUnitWebConfig(...) and included the #EnableWebMvc annotation to my imported Config. This seemed to add all the necessary converters. E.g.
#SpringJUnitWebConfig(MyTestConfig.class)
class MyTest {
#Inject
private WebApplicationContext wac;
private MockMvc mockMvc;
...
}
#EnableWebMvc
class MyTestConfig {
#Bean
...
}

Empty content body in checking exception scenarios with mockmvc

Overview:
I am going to test bad request (400) with a customized error message in Spring MVC Test. The test gets 400 as status; however the content body is empty.
The code snippets are as follows:
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
memberServiceController.setMemberDetailsApiController(mockMemberDetailsApiController);
memberServiceController.setResourceMessage(mockResourceMessage);
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilter(new ShallowEtagHeaderFilter())
.apply(documentationConfiguration(restDocumentation))
.build();
}
#Test
public void getMemberDetails_whenStoreIdIsNull_setStatusToBadRequest() throws Exception {
Mockito.doReturn("storeId is empty").when(mockResourceMessage).getMessage(MEMBER_ERROR_INVALID_STOREID);
mockMvc.perform(get(URL)
.header(REQUEST_HEADER_COOKIE, DEFAULT_COOKIE_VALUE)
.param(REQUEST_PARAM_MEMBERSHIP_IDENTIFIER, "MEMBER1"))
.andDo(MockMvcResultHandlers.print())
.andDo(document("memberServices/GetMemberDetailsNullStoreId",
requestHeaders(
headerWithName(REQUEST_HEADER_COOKIE).description(REQUEST_HEADER_COOKIE_DESCRIPTION)
),
requestParameters(
parameterWithName(REQUEST_PARAM_MEMBERSHIP_IDENTIFIER).description(REQUEST_PARAM_MEMBERSHIP_IDENTIFIER_DESCRIPTION)
)))
.andExpect(status().isBadRequest())
.andExpect(content().string(containsString("storeId is empty".toLowerCase())))
.andReturn().getResponse();
}
The raised exception is as follows:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /retailer1/memberDetails
Parameters = {membershipIdentifier=[MEMBER1]}
Headers = {Cookie=[SESSION=67421bc3-36da-4b64-9aca-94edf57211f6]}
Handler:
Type = com.blss.retailServices.memberServices.restServices.MemberRestController
Method = public org.springframework.http.HttpEntity<org.springframework.hateoas.Resource<com.blss.retailServices.memberServices.models.MemberDetailsResponseModel>> com.blss.retailServices.memberServices.restServices.MemberRestController.getMemberDetails(com.blss.retailServices.memberServices.models.MemberModel)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = com.blss.retailServices.InvalidRequestException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Response content
Expected: a string containing "storeid is empty"
but: was ""
The generated response in API Doc with asciidoc is as follows:
HTTP/1.1 400 Bad Request
Question:
Now I would appreciate it if anyone can help me find way to get bad request with my customized exception message ("storeId is empty") in order to be added to generated API documentation and have something like bellow as generated response in API documentation:
HTTP/1.1 400 Bad Request,
storeId is empty
The problem was related to exception handling in my code. I forgot to add GlobalControllerExceptionHandler class which is our exception handler to #SpringApplicationConfiguration in my test class. So after adding it as follows my problem solved:
#SpringApplicationConfiguration(classes = {
MemberRestControllerTest.class,
MemberRestController.class,
ResourceResultProcessor.class,
GlobalControllerExceptionHandler.class
})
public class MemberRestControllerTest {
...
}

MockMvc Test Spring throws org.springframework.web.HttpMediaTypeNotSupportedException

I am getting the follow exception org.springframework.web.HttpMediaTypeNotSupportedException trying to test a Json Controller.
The method in controller is:
#RequestMapping(value = "/report", method = RequestMethod.PUT)
public #ResponseBody DatosJsonVO report(#RequestHeader(value = "hash", required = true) String hash,
#RequestBody ReportVO report) {
}
My test method is the following:
#Test
public void reportarPreguntaSesionInvalida() throws Exception {
ReportVO report = new ReportVO();
report.setIdQuestion(1);
report.setIssue("Wrong answer");
mockMvc.perform(put("/json/report").header("hash", "123456789")
.accept(MediaType.APPLICATION_JSON).content(asJsonString(report))).andDo(print())
.andExpect(content().string("{\"code\":2,\"message\":\"Session error\",\"data\":null}"));
}
But, I get this response:
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /json/report
Parameters = {}
Headers = {hash=[8.16615469E8], Accept=[application/json]}
Handler:
Type = com.controller.json.QuestionsJsonController
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
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
My Spring Version is 4.0.0.RELEASE
You need to set the content type.
mockMvc.perform(put("/json/report")
.header("hash", "123456789")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(asJsonString(report))).andDo(print())
.andExpect(content().string("{\"code\":2,\"message\":\"Session error\",\"data\":null}"));
mockMvc.perform(put("/json/report").header("hash", "123456789")
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(report)))
.contentType(MediaType.APPLICATION_JSON)
.andDo(print())
.andExpect(content().string("{\"code\":2,\"message\":\"Session error\",\"data\":null}"));

Resources