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

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

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());
}

Spring Boot Web Test - 404 Not found

I am trying to test the Controller of a very simple GET request with #WebMvcTest but I'm getting 404 instead of 200 and the console does not give me anything useful to understand what is going on.
I've put a breakpoint at the beginning of the controller but it never arrives. If I run the application, the endpoint works as expected.
Here's my controller:
#RestController
public class RegistroClienteController {
#GetMapping("/api/registro-cliente")
public ResponseEntity<Void> crearCliente() {
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
And here's my test:
#RunWith(SpringRunner.class)
#WebMvcTest(RegistroClienteController.class)
#ContextConfiguration(classes = { SecurityConfig.class })
public class RegistroClienteControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
UserDetailsService userDetailsService;
#Test
public void test() throws Exception {
//#formatter:off
mockMvc
.perform(get("/api/registro-cliente"))
.andExpect(status().isOk());
//#formatter:on
}
}
And console's output:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/registro-cliente
Parameters = {}
Headers = {}
Handler:
Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = [[Cookie#624b3544 name = 'XSRF-TOKEN', value = 'f9d63654-4e21-4d41-b3bb-6767703268b5', comment = [null], domain = [null], maxAge = -1, path = '/', secure = false, version = 0, httpOnly = false]]
I was having the same error and after hours of searching found that the error is due to controller not being registered. The problem is described here.
Apparently, the following is not enough.
#WebMvcTest(controllers = {<ControllerToTest>.class})
You need to do,
#WebMvcTest(controllers = {<ControllerToTest>.class})
#Import(<ControllerToTest>.class)
I can try to change the annotations
#WebMvcTest(RegistroClienteController.class)
to
#SpringBootTest(classes = {your application class}.class)

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

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!

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