java.lang.AssertionError: Status 404 - java

Im having 404 error on this test , Im trying to figure out why its giving me this error could someone help me please
this is my controller :
#PostMapping("/infoUtile/add/{idUser}")
public InformationUtile addOrEditProcedure(#PathVariable(value = "idUser") Long id){
User user = this.userService.getUser(id);
InformationUtile info = new InformationUtile();
info.setUser(user);
return this.infoUtileService.addOrEditInfoUtile(info);
}
and this is the test that I wrote
#Autowired
private MockMvc mockMvc;
#MockBean
InformationUtileService informationUtileService;
#MockBean
UserService userService;
ObjectMapper mapper = new ObjectMapper();
#Test
public void givenInformationsUtiles_whenGetInfoUtiles_thenReturnJsonArray()
throws Exception {
InformationUtile informationUtile = new InformationUtile();
informationUtile.setId(1);
informationUtile.setContent("oumaima");
informationUtile.setDescription("test");
Media medias = new Media();
medias.setType("image/png");
medias.setUrl("C:\\files\\actualite\\32769\\adobexd.png");
List<Media> allMedias = new ArrayList<Media>();
allMedias.add(medias);
informationUtile.setMedias(allMedias);
OngoingStubbing<User> user = Mockito.when(userService.getUser(Mockito.anyLong())).thenReturn(new User());
Mockito.when(informationUtileService.addOrEditInfoUtile(Mockito.any(InformationUtile.class))).thenReturn(informationUtile);
mockMvc.perform(post("/infoUtile/add/{id}",informationUtile.getId())
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsBytes(informationUtile)))
.andExpect(status().isOk());
}
log

I had the same issue and in my case the solution was to use full path
from #RequestMapping (controller annotation) + #PostMapping (method annotation)
I don't know if this is the case for you. You don't show your controller class. But if you have something like this:
#RestController
#RequestMapping("/api/v1")
public class SomeController {
#PostMapping("/infoUtile/add/{idUser}")
public InformationUtile addOrEditProcedure(#PathVariable(value = "idUser") Long id) {...}
}
then the path in test will be
mockMvc.perform(post("/api/v1/infoUtile/add/{idUser}",informationUtile.getId())

Related

Not able to call the controller method using MockMvc

I am not able to get how to call the controller method(API) in this case. How to send the MultipartFile as request parameter and how to pass the HttpServletRequest so that mockMvc can call the actual method for testing.
#RunWith(SpringRunner.class)
public class PartnerSiteLoadControllerTest {
private MockMvc mockMvc;
#Mock
private PartnerSiteUploadService partnerSiteUploadService;
#InjectMocks
private PartnerSiteLoadController partnerSiteLoadController;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(partnerSiteLoadController)
.setControllerAdvice(new PartnerExceptionHandlerMapper()).build();
}
#Test
public void uploadSitesInBulk()throws Exception {
String userId = "userId";
HttpServletRequest request = mock(HttpServletRequest.class);
UserPrincipal userPrincipal = new UserPrincipal();
userPrincipal.setId("id");
BulkUploadResponseDTO bulkUploadResponseDTO = new BulkUploadResponseDTO();
FileInputStream inputFile = new FileInputStream( "src/test/resources/PartnerSites_2019-09-04_v1.xlsx");
MockMultipartFile file = new MockMultipartFile("PartnerSites_2019-09-04_v1.xlsx", "PartnerSites_2019-09-04_v1.xlsx", "multipart/form-data", inputFile);
when(file.getOriginalFilename()).thenReturn("PartnerSites_2019-09-04_v1.xlsx");
when(request.getAttribute("userPrincipal")).thenReturn(userPrincipal);
when(partnerSiteUploadService.uploadSitesInBulk(userId,file)).thenReturn(bulkUploadResponseDTO);
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v4/slm/partners/sites/import")
.file(file).contentType(MediaType.MULTIPART_FORM_DATA).requestAttr("userPrincipal",userPrincipal))
.andExpect(status().isOk());
verify(partnerSiteUploadService,times(1)).uploadSitesInBulk(userId,file);
verifyNoMoreInteractions(partnerSiteUploadService);
}
}
Controller class method
#RestController
#RequestMapping("/v4/slm/partners/sites/import")
#Api(value = "Site Bulk Upload Service")
#Slf4j
#Validated
public class PartnerSiteLoadController {
private PartnerSiteUploadService partnerSiteUploadService;
#Autowired
public PartnerSiteLoadController(PartnerSiteUploadService partnerSiteUploadService) {
this.partnerSiteUploadService = partnerSiteUploadService;
}
#PostMapping(value = "", headers = ("content-type=multipart/*"))
#ApiOperation(value = "Import sites in bulk")
public ResponseEntity<BulkUploadResponseDTO> uploadSitesInBulk(#RequestParam("file") MultipartFile excelFile, HttpServletRequest request){
UserPrincipal userPrincipal = (UserPrincipal) request.getAttribute("userPrincipal");
String userId = userPrincipal.getId();
log.info("Received excel file with name {}......",excelFile.getOriginalFilename());
if(!excelFile.isEmpty()){
return ResponseEntity.status(HttpStatus.CREATED).body(partnerSiteUploadService.uploadSitesInBulk(userId,excelFile));
}
else{
throw new BadRequestException("Received empty excel file");
}
}
}
while executing the test I am getting the 400 error code. the mockmvc is not calling the original API.

unit testing in spring boot giving error when exception thrown in service

So, I have this unit test that I need to run.
#MockBean
private AppServiceImpl appService;
#Test
public void shouldThrowExceptionWhenAppIdIsNull() throws Exception {
File inputFile = this.getJsonFile();
RequestDto requestDto = objectMapper.readValue(inputFile.getAbsoluteFile(),
RequestDto.class);
AppData appData = requestDto.getAppData();
appData.setAppId(null);
requestDto.setAppData(appData);
when(appService.getUrl(requestDto, "header")).thenThrow(new RequestNotValidException());
String payload = objectMapper.writeValueAsString(requestDto);
this.mockMvc.perform(post(Base_URL + "app/requesturl")
.contentType(contentType).content(payload).header(this.Header, "header"))
.andExpect(status().is4xxClientError());
}
Interface for service:
SO when I run this test, it throws an exception and doesn't actually assert the test here.
I have added #ResponseStatus(HttpStatus.BAD_REQUEST) on top of RequestNotValidException and it extends RunTimeException
And in the second test case, I get empty response. I tried this API vis Postman and I get the response. Everything works fine there.
#Test
public void getCardRegistration() throws Exception {
File inputFile = this.getJsonFile();
RequestDto requestDto = objectMapper.readValue(inputFile.getAbsoluteFile(), RequestDto.class);
ResponseDto responseDto = new ResponseDto();
responseDto.setURL(AuthUtils.randomStringToken(35));
given(appService.getRegistrationUrl(requestDto, "header")).willReturn(responseDto);
String payload = objectMapper.writeValueAsString(requestDto);
MvcResult mvcResult = this.mockMvc.perform(post(Base_URL + "app/requesturl")
.contentType(contentType).content(payload).header(this.Header, "header"))
.andReturn();
String contentAsString = mvcResult.getResponse().getContentAsString();
}
Controller content:
#Autowired
IAppService appService;
#RequestMapping(value = "/app/requesturl", method = RequestMethod.POST)
public ResponseDto getCardsRegistration(#RequestBody #Valid RequestDto requestDto, #RequestHeader(value="X-App-Name", required = true) String header) throws RequestNotValidException, JsonProcessingException {
log.info("Request received in controller: "+ mapper.writeValueAsString(cardRegistrationRequestDto));
log.info("Header value: "+ header);
return this.appService.getRegistrationUrl(requestDto, header);
}
Test Class:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class AppRestControllerTest {
protected String Base_URL = "/app";
protected String Header = "X-App-Name";
protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Charset.forName("utf8"));
#Autowired
protected MockMvc mockMvc;
protected ObjectMapper objectMapper = new ObjectMapper();
#MockBean
private AppServiceImpl appService;
#Mock
private AppRegistrationRepository appRegistrationRepository;
#Before
public void setUp() throws Exception {
MapperFacade mapperFacade = new DefaultMapperFactory.Builder().build().getMapperFacade();
appService = new AppServiceImpl(appRegistrationRepository, mapperFacade);
}
What did I miss here?
Try to use
#RunWith(SpringRunner.class)
#WebMvcTest(YourController.class)
public class AppRestControllerTest {
Or
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
#AutoConfigureMockMvc
public class AppRestControllerTest {
In your tests

spring boot unit test assertion error

Working on a spring boot based Rest project I have a controller like this
which calls service and service layer call dao layer. Now I am writing unit test code for controllers. when I run this the error says
java.lang.AssertionError: expected:<201> but was:<415>
I don't know where I am doing wrong:
public class CustomerController {
private static final Logger LOGGER = LogManager.getLogger(CustomerController.class);
#Autowired
private CustomerServices customerServices;
#Autowired
private Messages MESSAGES;
#Autowired
private LMSAuthenticationService authServices;
#RequestMapping(value = "/CreateCustomer", method = RequestMethod.POST)
public Status createCustomer(#RequestBody #Valid Customer customer, BindingResult bindingResult) {
LOGGER.info("createCustomer call is initiated");
if (bindingResult.hasErrors()) {
throw new BusinessException(bindingResult);
}
Status status = new Status();
try {
int rows = customerServices.create(customer);
if (rows > 0) {
status.setCode(ErrorCodeConstant.ERROR_CODE_SUCCESS);
status.setMessage(MESSAGES.CUSTOMER_CREATED_SUCCESSFULLY);
} else {
status.setCode(ErrorCodeConstant.ERROR_CODE_FAILED);
status.setMessage(MESSAGES.CUSTOMER_CREATION_FAILED);
}
} catch (Exception e) {
LOGGER.info("Cannot Create the Customer:", e);
status.setCode(ErrorCodeConstant.ERROR_CODE_FAILED);
status.setMessage(MESSAGES.CUSTOMER_CREATION_FAILED);
}
return status;
}
}
The test for the CustomerController.
public class CustomerControllerTest extends ApplicationTest {
private static final Logger LOGGER = LogManager.getLogger(CustomerControllerTest.class);
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#MockBean
private CustomerController customerController;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
Status status = new Status(200,"customer created successfully","success");
String customer = "{\"customerFullName\":\"trial8900\",\"customerPhoneNumber\": \"trial8900\", \"customerEmailID\": \"trial8900#g.com\",\"alternateNumber\": \"trial8900\",\"city\": \"trial8900\",\"address\":\"hsr\"}";
#Test
public void testCreateCustomer() throws Exception {
String URL = "http://localhost:8080/lms/customer/CreateCustomer";
Mockito.when(customerController.createCustomer(Mockito.any(Customer.class),(BindingResult) Mockito.any(Object.class))).thenReturn(status);
// execute
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post(URL)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON_UTF8)
.content(TestUtils.convertObjectToJsonBytes(customer))).andReturn();
LOGGER.info(TestUtils.convertObjectToJsonBytes(customer));
// verify
MockHttpServletResponse response = result.getResponse();
LOGGER.info(response);
int status = result.getResponse().getStatus();
LOGGER.info(status);
assertEquals(HttpStatus.CREATED.value(), status);
}
}
HTTP status 415 is "Unsupported Media Type". Your endpoint should be marked with an #Consumes (and possibly also #Produces) annotation specifying what kinds of media types it expects from the client, and what kind of media type it returns to the client.
Since I see your test code exercising your production code with MediaType.APPLICATION_JSON_UTF8, you should probably mark your endpoint as consuming and producing APPLICATION_JSON_UTF8.
Then you also need to make sure that there is nothing terribly wrong going on in your error handling, because in the process of catching the exceptions generated by your production code and generating HTTP responses, your error handling code may be generating something different, e.g. generating an error status response with a payload containing an HTML-formatted error message, which would have a content-type of "text/html", which would not be understood by your test code which expects json.
Use the below base test class for your setUp and converting json to string and string to json
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = Main.class)
#WebAppConfiguration
public abstract class BaseTest {
protected MockMvc mvc;
#Autowired
WebApplicationContext webApplicationContext;
protected void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
protected String mapToJson(Object obj) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
}
protected <T> T mapFromJson(String json, Class<T> clazz)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, clazz);
}
}
Also verify that your post call has happened or not check the below sample
Mockito.doNothing().when(customerServices).create(Mockito.any(Customer.class));
customerServices.create(customer);
Mockito.verify(customerServices, Mockito.times(1)).create(customer);
RequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI)
.accept(MediaType.APPLICATION_JSON).content(inputInJson)
.contentType(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
assertEquals(HttpStatus.OK.value(), response.getStatus());

Spring Testing - java.lang.IllegalArgumentException: Not enough variable values available to expand

I am writing Unit Tests for the below REST Controller which takes a UserID and grants a List of Authorities to that user.
#RestController
#RequestMapping("/user")
#Api(value = "User", description = "User API")
public class UserController{
// some code
#RequestMapping(method = RequestMethod.POST, value = "/{userId}/grantAuthz")
#ApiOperation(value = "GrantAuthz", notes = "Grant Authorization")
public Collection<UserEntity.UserAuthz> grantAuthz(#PathVariable("userId") String userId,
#RequestBody ArrayList<String> authorities) {
UserEntity userEntity = userRepository.findOne(userId);
if(userEntity == null) {
//TODO: throw and send resource not found
return null;
}
log.debug("Authorities to be granted to user " + userId + " are : " + authorities);
for(String authz : authorities) {
log.debug("Adding Authorization " + authz);
userEntity.addUserAuthz(authz);
}
userRepository.save(userEntity);
return userEntity.getAuthorities();
}
}
I wrote the below Unit Test for the UserController
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class UserControllerTest {
private final Log log = LogFactory.getLog(getClass());
private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Charset.forName("utf8"));
private MockMvc mockMvc;
private HttpMessageConverter mappingJackson2HttpMessageConverter;
private final String USER_URL = "/{userId}/grantAuthz";
private final String USER_ID = "111";
private final String USER_NAME = "MockUser";
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private UserRepository userRepository;
private String createdToken = null;
#Autowired
void setConverters(HttpMessageConverter<?>[] converters) {
this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream().filter(
hmc -> hmc instanceof MappingJackson2HttpMessageConverter).findAny().get();
Assert.assertNotNull("the JSON message converter must not be null",
this.mappingJackson2HttpMessageConverter);
}
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONObject json = new JSONObject();
json.put("grantList",grantList);
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL)
.contentType(contentType)
.param("userId",USER_ID)
.param("authorities",json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
}
When executed, my test is throwing an Illegal Argument Exception:
"Not enough variable values available to expand 'userId'"
I am sending the required URL Parameters using the .param() method in the test, what am I doing wrong ? I reffered this possible duplicate question but did not find it much useful. Using RestTemplate in Spring. Exception- Not enough variables available to expand
I found out what I am doing wrong, using param() method is not the right way here as I have #PathVariable and #RequestBody in my Controller Methods as the parameters.
public Collection<UserEntity.UserAuthz> grantAuthz(#PathVariable("userId") String userId,
#RequestBody ArrayList<String> authorities) {
So I passed the #PathVariable in the post() method of the test.
MockMvcRequestBuilders.post(USER_URL,USER_ID)
As the required type is #RequestBody ArrayList<String> instead of using the JSONObject I used JSONArrayand used the content() method to send the JSONArray as the string.
Here are the changes I have made to the Test Method.
#Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONArray json = new JSONArray();
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL,USER_ID)
.contentType(contentType)
.content(json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
#Test
public void getOneContactAPI() throws Exception {
String id = "8";
mvc.perform(MockMvcRequestBuilders.get("/api/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("id").exists());
}

EasyMock Controller Mapping and Status Code Tests

I'm trying to test my controller mapping and the response http status codes. Therefore I'm using the RequestMappingHandlerAdapter and the RequestMappingHandlerMapping.
My Controller
#Controller
#RequestMapping(value ="/user")
public class AdminSpringController {
#Autowired
public UserAdminService userService;
private final Logger log = LoggerFactory.getLogger(AdminSpringController.class);
#RequestMapping(method = RequestMethod.GET, consumes = "application/json", produces = "application/json")
#ResponseStatus(HttpStatus.OK)
public List<User> getUsers() {
log.trace("Request to get all users.");
return userService.getUsers();
}
}
and my Test class:
public class AdminSpringControllerTests {
AdminSpringController cut;
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private RequestMappingHandlerAdapter adapter;
private RequestMappingHandlerMapping handlerMapping;
#Test
public void testGetSc() throws Exception{
adapter = new RequestMappingHandlerAdapter();
handlerMapping = new RequestMappingHandlerMapping();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setRequestURI("/user");
request.addHeader("Accept", "application/json");
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
ModelAndView mav = adapter.handle(request, response, handler);
assertNotNull(mav);
}
}
But I'm getting an NullPointerException in the row Object handler = ...
I simply want to test my mapping and then check the HTTP status codes from my response. Is this the right approach or is my test implementation totally wrong. For the tests I need to use EasyMock. As next step I wanted to test if the response status codes (response.getStatus()) is equals to SC_OK (200).
Thx for any help :)
I am using SpringMvc Test approach, mixed with EasyMock, which is a good approach.
#ContextConfiguration("ProjectFacadeTest-context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class AdminSpringControllerTests {
...
private MockMvc mockMvc;
...
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(imageController).build();
}
EasyMock.expect(mockPersistedProjectService.getImages(EasyMock.anyLong())).andReturn(images);
EasyMock.replay(mockPersistedProjectService);
MvcResult result =
this.mockMvc.perform(get("/resources/projects/1000/images")).andExpect(content().type("application/json"))
.andExpect(status().isOk()).andReturn();
MockHttpServletResponse response = result.getResponse();
//VERIFY RESPONSE
EasyMock.verify(mockPersistedProjectService);
XML FILE
<bean id="mockArtifactService" class="org.easymock.EasyMock"
factory-method="createStrictMock" primary="true">
<constructor-arg value="com.xxxxxx.service.ArtifactService" />
</bean>

Categories