Spring Boot Web Test - 404 Not found - spring

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)

Related

Junit test case in springboot giving response null in get API

Trying to implement junit testcases in my Spring-boot application. the test class ProjectStatusControllerTestjava defined a simple get function for fetching data using mockmvc framework provided by junit 4. The API gives response 200 OK, but no data in data object of the json response, refer below the code snippet and the response of the server .Using maven command mvn test -Dtest=ProjectStatusControllerTest for execution.
#RunWith(SpringRunner.class)
#WebMvcTest(ProjectStatusController.class)
#ContextConfiguration(classes = {ProjectStatusController.class,ProjectStatusService.class, ProjectStatusServiceImpl.class,
ProjectStatusRepository.class, SpringSecurityonfig.class, RestAuthenticationEntryPoint.class,
JwtParser.class, OodlesProperties.class, LeadDataView.class})
#AutoConfigureWebMvc
public class ProjectStatusControllerTest {
#MockBean
private ProjectStatusService projectStatusService;
#Autowired
MockMvc mockMvc;
#Test
public void getAllProjectStatus()throws Exception {
String str = "http://localhost:9000/" +UrlMappings.GET_ALL_PROJECT_STATUS;
String authToken = "eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSTFVejI4YlJSUitkbXdTa2ladGs3WVVTa3Fob0o2NmRrTHNKSXFFNnRpbTNiRGVMVjViVVMxVjBYaDNiRSt6M2xsbXhvN05BY1NGQXozQUFRNGN1Q0loVmVLSXhCMGhvWjQ0Y29FRFZcLzRGNE0zYWE3Y24yTU8zNzcxOXYrZmJlZklYWktXQVd4N3ZHNXo3QVpXR3pcL3VFaFlhazNrQXdOVGJjcWRDVVZOeUdwVjgrXC91NzBlaHBXVzdCSVE5SU9xSTlTajBpTGRsUUx6akhwRGlJcWhreHljUVFaUWNMVEkzaGhnTEdtYjBHV1l1NUF3YnIxaUF4SkxpQmhOK2Nxd2NMdWdZWDUrcEZOK3ZRRCtBaFM2TnNWeEUrVU5QTVZYSGdteXVKeHpGSkVwRHpqd2srQ0JNY1pacTREeFlLY3hhUkMxM055MXBnWnU2Y3hYRGNXSmpWSFVRcFNNSGxtYndVWCt5U2tWUGJ1VEJmRXVJTFYyc1IybzBaOEVpcElsWEdMYTdxbW9kc3o0dlllXC9cL25GMDg5dlwvcDZHMUJGa2h5UVkwSkdBQzNNbmU5QnZVXC9IcGs2ODJWNzc4NDNFYVlCUk5xeDRvdUZNczVOdkY0dGJiZm9jUVV0anE3QmFMKzl0YitjNTJ1OURaTCs2UjNiMThIbTEwWjR2NnU5N092dFwvWjNmTUtuUjM4dE8wVkNubHNLTWRGMStpeHRwNVJVY1BqUVVBOXhYaG9zRkJwWTJEY3AwTGlmbWlvRGtuMzcrT2Z2dlwvTitiYVMxcnRaYUpPdVhzdUNCZXVSNEVQbVU3ODh5NkRneWpNcm50c1BjTVIzXC9ydHNxUzJWSUo2YWw1K25PTDc2dzhQUGZwU05OS3kwNEJvSkFuNW1jZUk3QXlXeGh3WlNTcExZMFlSbGozZzk2cnZzUTlxQ3JNK0VHcmRnalFhMGp4bnJ0TStIbXA0ckxHU0trUUM5VUZ0bHNvRk1jNm1VbUFQblBLWGoyVFNNNTF3cVlsXC9OYmFSTmxwK0ZWRHhQV2FmOUNGdkZqeGxOdHluMTF1VWs0N3ZZSEJmajVvQWxwRnlUYU1BdVF4TEpIbGZhZWg2UCtoOThOTkcwdnF3aG8rRDJcL1wvd1JqWmpuRVo3eFJzd25mUXBHU1FneTFtd2ZmZkxyNXRjXC9rMjhXSUdWQ1J1TGNNYk11bm1VMEtsaXJPMWIxcEdRNzlvT2EwM1FWTEU4TWxacHBLM2d4VnBwdXRhNWdKWllkcDJKVjBXMHgxZzRyaVhRUFBkWmpxZXpZamFyZE9LNmJEUjAyK1d6V0ZDekYwdjJhZ1wvXC9NcEVpNTdEVHRCbWE3Rk91VmtudnYwQ25WSzBuNXk3RzVYbldkWnIxczJuY1QrOFp6NFlsMTBybFZ2VnV5a2w3ZWIxYmRodW5ZSjRjbCt6MjhDdVllU2RENTZSd25aZXk1WHJKR1VxOVwvWTc0aXJWN1djRVhEU3hxdWFuaFp3eXNhcm1sNFZjT21odXNhWHROd1E4UHJHdDdRY0ZQRG14cmVHa1Z4bWFYNXpiSTR2Vm4rQmZKUWdnMkdCUUFBIiwic3ViIjoibWFuZWVzaEBvb2RsZXMuaW8iLCJyb2xlcyI6WyJST0xFX0FOT05ZTU9VUyIsIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX09PRExFUyIsIlJPTEVfQkQiLCJST0xFX0hSIiwiUk9MRV9DT05URU5UV1JJVEVSIiwiUk9MRV9JTSIsIlJPTEVfUE1PIiwiUk9MRV9BQ0NPVU5UUyIsIlJPTEVfREFTSEJPQVJEX0FETUlOIiwiUk9MRV9SRVNPVVJDSU5HX0FETUlOIiwiUk9MRV9BQ0NPVU5UU19BRE1JTiIsIlJPTEVfTEVHQUwiLCJST0xFX1FVRVNUSU9OX0JBTksiLCJST0xFX0xFR0FMX0FETUlOIiwiUk9MRV9CRF9DRU5UUkFMIl0sImdyYWRlIjoiQyIsImlzU3RlYWx0aE1vZGUiOmZhbHNlLCJyYW5rIjoxLCJpZCI6MSwidHlwZSI6InVzZXIiLCJleHAiOjE2NTYzNDA3MzAsInVzZXJJZCI6MSwiaXNTdXBlcnZpc2VyIjp0cnVlLCJpYXQiOjE2NTYzMDgzMzB9.RAu-YFfCyD90gXMkk9BIvS5GU046QIKhETBkdgoziWk";
mockMvc.perform(get(str)
.header(HttpHeaders.AUTHORIZATION,authToken)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk()).toString();
}
}
Response ::::::
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/v1/projectStatus/getAllProjectStatus
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Authorization:"eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSTFVejI4YlJSUitkbXdTa2ladGs3WVVTa3Fob0o2NmRrTHNKSXFFNnRpbTNiRGVMVjViVVMxVjBYaDNiRSt6M2xsbXhvN05BY1NGQXozQUFRNGN1Q0loVmVLSXhCMGhvWjQ0Y29FRFZcLzRGNE0zYWE3Y24yTU8zNzcxOXYrZmJlZklYWktXQVd4N3ZHNXo3QVpXR3pcL3VFaFlhazNrQXdOVGJjcWRDVVZOeUdwVjgrXC91NzBlaHBXVzdCSVE5SU9xSTlTajBpTGRsUUx6akhwRGlJcWhreHljUVFaUWNMVEkzaGhnTEdtYjBHV1l1NUF3YnIxaUF4SkxpQmhOK2Nxd2NMdWdZWDUrcEZOK3ZRRCtBaFM2TnNWeEUrVU5QTVZYSGdteXVKeHpGSkVwRHpqd2srQ0JNY1pacTREeFlLY3hhUkMxM055MXBnWnU2Y3hYRGNXSmpWSFVRcFNNSGxtYndVWCt5U2tWUGJ1VEJmRXVJTFYyc1IybzBaOEVpcElsWEdMYTdxbW9kc3o0dlllXC9cL25GMDg5dlwvcDZHMUJGa2h5UVkwSkdBQzNNbmU5QnZVXC9IcGs2ODJWNzc4NDNFYVlCUk5xeDRvdUZNczVOdkY0dGJiZm9jUVV0anE3QmFMKzl0YitjNTJ1OURaTCs2UjNiMThIbTEwWjR2NnU5N092dFwvWjNmTUtuUjM4dE8wVkNubHNLTWRGMStpeHRwNVJVY1BqUVVBOXhYaG9zRkJwWTJEY3AwTGlmbWlvRGtuMzcrT2Z2dlwvTitiYVMxcnRaYUpPdVhzdUNCZXVSNEVQbVU3ODh5NkRneWpNcm50c1BjTVIzXC9ydHNxUzJWSUo2YWw1K25PTDc2dzhQUGZwU05OS3kwNEJvSkFuNW1jZUk3QXlXeGh3WlNTcExZMFlSbGozZzk2cnZzUTlxQ3JNK0VHcmRnalFhMGp4bnJ0TStIbXA0ckxHU0trUUM5VUZ0bHNvRk1jNm1VbUFQblBLWGoyVFNNNTF3cVlsXC9OYmFSTmxwK0ZWRHhQV2FmOUNGdkZqeGxOdHluMTF1VWs0N3ZZSEJmajVvQWxwRnlUYU1BdVF4TEpIbGZhZWg2UCtoOThOTkcwdnF3aG8rRDJcL1wvd1JqWmpuRVo3eFJzd25mUXBHU1FneTFtd2ZmZkxyNXRjXC9rMjhXSUdWQ1J1TGNNYk11bm1VMEtsaXJPMWIxcEdRNzlvT2EwM1FWTEU4TWxacHBLM2d4VnBwdXRhNWdKWllkcDJKVjBXMHgxZzRyaVhRUFBkWmpxZXpZamFyZE9LNmJEUjAyK1d6V0ZDekYwdjJhZ1wvXC9NcEVpNTdEVHRCbWE3Rk91VmtudnYwQ25WSzBuNXk3RzVYbldkWnIxczJuY1QrOFp6NFlsMTBybFZ2VnV5a2w3ZWIxYmRodW5ZSjRjbCt6MjhDdVllU2RENTZSd25aZXk1WHJKR1VxOVwvWTc0aXJWN1djRVhEU3hxdWFuaFp3eXNhcm1sNFZjT21odXNhWHROd1E4UHJHdDdRY0ZQRG14cmVHa1Z4bWFYNXpiSTR2Vm4rQmZKUWdnMkdCUUFBIiwic3ViIjoibWFuZWVzaEBvb2RsZXMuaW8iLCJyb2xlcyI6WyJST0xFX0FOT05ZTU9VUyIsIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX09PRExFUyIsIlJPTEVfQkQiLCJST0xFX0hSIiwiUk9MRV9DT05URU5UV1JJVEVSIiwiUk9MRV9JTSIsIlJPTEVfUE1PIiwiUk9MRV9BQ0NPVU5UUyIsIlJPTEVfREFTSEJPQVJEX0FETUlOIiwiUk9MRV9SRVNPVVJDSU5HX0FETUlOIiwiUk9MRV9BQ0NPVU5UU19BRE1JTiIsIlJPTEVfTEVHQUwiLCJST0xFX1FVRVNUSU9OX0JBTksiLCJST0xFX0xFR0FMX0FETUlOIiwiUk9MRV9CRF9DRU5UUkFMIl0sImdyYWRlIjoiQyIsImlzU3RlYWx0aE1vZGUiOmZhbHNlLCJyYW5rIjoxLCJpZCI6MSwidHlwZSI6InVzZXIiLCJleHAiOjE2NTYzNDA3MzAsInVzZXJJZCI6MSwiaXNTdXBlcnZpc2VyIjp0cnVlLCJpYXQiOjE2NTYzMDgzMzB9.RAu-YFfCyD90gXMkk9BIvS5GU046QIKhETBkdgoziWk", Accept:"application/json"]
Body = null
Session Attrs = {}
Handler:
Type = com.oodles.controller.projectStatus.ProjectStatusController
Method = com.oodles.controller.projectStatus.ProjectStatusController#getAllProjectStatus(String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Content-Type:"application/json", 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 = application/json
Body = {"data":[],"message":"No Record Found","timestamp":1656308435497,"status":200,"isSuccess":true} -----NO DATA IN JSON
Forwarded URL = null
Redirected URL = null
Cookies = []

MockMvc with SpringBootTest is throwing exception HttpMediaTypeNotSupportedException when testing the controller

I am testing request validation in Spring RestController with the help of integration testing and MockMvc.
ControllerTest.java
#ExtendWith(MockitoExtension.class)
#SpringBootTest(classes = Controller.class)
#AutoConfigureMockMvc(addFilters = false)
class ControllerTest {
private ObjectMapper objectMapper;
#MockBean
private Service service;
#Autowired
private MockMvc mockMvc;
#BeforeEach
void setUp() {
objectMapper = new ObjectMapper();
}
#Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("test#mail.com")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.characterEncoding("utf-8"))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
Controller.java :
#Slf4j
#RestController
public class Controller {
private final Service service;
public Controller(Service service) {
this.service = service;
}
#PostMapping(value = "/api/create", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<GenericResponse<Response>> createOrAdd(#RequestBody #Valid Request request, Errors errors) {
GenericResponse<Response> genericResponse = new GenericResponse<>();
try {
if (errors.hasErrors()) {
throw new RequestParamsException(errors.getAllErrors());
}
Response response = service.createOrAdd(request);
genericResponse.setData(response);
return ResponseEntity.ok().body(genericResponse);
} catch (RequestParamsException ex) {
genericResponse.setErrors(ex.getErrors());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(genericResponse);
}
}
Error :
WARN 17304 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"test#mail.com"}
Session Attrs = {}
Handler:
Type = com.org.controller.Controller
Method = com.org.controller.Controller#createOrAdd(Request, Errors)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Accept:"application/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, multipart/mixed, */*"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<415>
Expected :400
Actual :415
I have used the correct Content-Type and Accept Headers while making a call in Test.java using mockMvc, but still it's giving HttpMediaTypeNotSupportedException. Tried many combinations in Accept and Content-Type but still not working.
I have read many SO questions related to this exception, but couldn't find what's the issue here.
Still not able to figure out why it's saying HttpMediaTypeNotSupportedException.
Update : After removing addFilters = false as suggested, not able to find the handler itself.
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"test#mail.com"}
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken#7a687d8d}
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 = 403
Error message = Forbidden
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 = []
java.lang.AssertionError: Status expected:<400> but was:<403>
Expected :400
Actual :403
Request :
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class CreateAgencyRequest {
#NotNull(message = "name can't be null")
#JsonProperty(value = "name")
#Pattern(regexp = REGEX_CONST, message = "name is not valid")
private String name;
#NotNull(message = "primary_email_address can't be null")
#JsonProperty(value = "primary_email_address")
private String primaryEmail;
}
Lets take a look at your test.
#WebMvcTest(classes = Controller.class)
#AutoConfigureMockMvc(addFilters = false)
class ControllerTest {
private ObjectMapper objectMapper;
#MockBean
private Service service;
#Autowired
private MockMvc mockMvc;
#Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("test#mail.com")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.characterEncoding("utf-8"))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
First the #ExtendWith(MockitoExtension.class) doesn't add anything as you are using, correctly, the #MockBean annotation which is handled by Spring. So you should remove that.
Next the #SpringBootTest is for bootstrapping the full application to run an integration test. What you want is a sliced test for the web, so instead of #SpringBootTest use #WebMvcTest this will make your test considerably faster. You can then also remove #AutoConfigureMockMvc as that is added by default.
You disabled all filters with #AutoConfigureMockMvc(addFilters = false) probably due to the 403 you got. The 403 you have is the result of enabling CSRF (enabled by default) and not adding that to the request. If you don't want CSRF (you probably want it) either disable that in the Security configuration, or if you want it modify your request.
Looking at the error you have the culprit is the characterEncoding being added to the content type, so you probably want/should remove that.
With all that your test should look something like this.
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
#WebMvcTest(Controller.class)
class ControllerTest {
private ObjectMapper objectMapper = new ObjectMapper();
#MockBean
private Service service;
#Autowired
private MockMvc mockMvc;
#Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("test#mail.com")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.with(csrf()) // Add CSRF field for security
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
NOTE: If you also have authentication in place you might also need to add a user/password to the request as explained here
I think you are missing #WebMvcTest(controllers = Controller.class)

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

Spring runner test return 404 for API test

I am writing API test cases for one of my controllers, but it is resulting with a 404.
I thought it would be a typo but it is not. Below are the code snippets.
RestController: package: com.x.y.address.controller (src/main)
#RestController
public class AddressInternalController {
#PostMapping(value = "/v1/address-service/internal/company/address", produces = "application/json;charset=UTF-8")
#ResponseStatus(OK)
public #ResponseBody ResponseEntity<AddressModel> createCompanyAddress()
throws AddressException, BadRequestException {
return ok("SUCCESS");
}
}
My Test class: package com.x.y.address.controller (src/test)
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = TestApp.class, initializers = ConfigFileApplicationContextInitializer.class)
#WebMvcTest(controllers = AddressInternalController.class, secure = false)
public class AddressInternalControllerTest {
#Autowired
private MockMvc mvc;
#Before
public void init() {}
#Test
public void createAddressTest_when_invalid_company() throws Exception {
this.mvc.perform(post("/v1/address-service/internal/company/address").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}
My app uses spring security and to bypass that I have created a TestAPP class so that it will help me build only the config without security.
TestApp: package com.x.y.address (src/test)
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
// #ComponentScan({"com.x.y.address.controller.AddressInternalController"})
public class TestApp {
}
Above are the structure of the class.
Initially I thought may be the program does not scan the controller package and hence the 404. Hence added the componentScan. But that did not help.
Searched through a lot of stack over flow but most of the 404 are due to a type but it is not in my case.
Error log:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /v1/address-service/internal/company/address
Parameters = {}
Headers = {Content-Type=[application/json]}
Body = <no character encoding set>
Session Attrs = {}
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 = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :404
Any help shall be greatly appreciated.
I replaced:
#EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class})
// #ComponentScan({"com.x.y.address.controller.AddressInternalController"})
public class TestApp {
}
with:
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class})
// #ComponentScan({"com.x.y.address.controller.AddressInternalController"})
public class TestApp {
}
and it worked.
UPDATE 1:
I noticed, in your #ComponentScan you use the path to the class itself, but you should point to the package with your controller. If you want to specify a class, use basePackageClasses property of #ComponentScan

"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
...
}

Resources