How to specify #RequestMapping params in MockMvc - java

I have a controller:
#Controller
#RequestMapping(value = "/bookForm")
public class BookFormController {
#Autowired
private BookHttpRequestParser parser;
#Autowired
private BooksService booksService;
#RequestMapping(params = "add", method = RequestMethod.POST)
public String addBook(HttpServletRequest request) {
try {
Book newBook = parser.createBookFromRequest(request);
booksService.addBook(newBook);
} catch (InvalidTypedParametersException e) {
}
return "redirect:index.html";
}
This Controller has a method for adding book to DB. Method has #RequestMapping annotation with params = "add" value.
Im trying to set this params criteria to controller unit test method:
#Test
public void addBook() throws Exception{
HttpServletRequest request = mock(HttpServletRequest.class);
Book book = new Book();
when(parser.createBookFromRequest(request)).thenReturn(book);
mockMvc.perform(post("/bookForm", "add"))
.andExpect(status().isOk())
.andExpect(view().name("redirect:index.html"));
}
Where to specify this #ResuetsMapping params value?
This:
mockMvc.perform(post("/bookForm", "add"))
doesn't work at all.

The following should work.
mockMvc.perform(post("/bookForm?add="))

use RequestBuilder requestBuilders;
object to build your request
requestBuilders = MockMvcRequestBuilders.get("URL/{Pathvariable}","PathvariableValue")
.contentType(MediaType.APPLICATION_JSON)
.header("HeaderName", HeaderValue)
.param("ParameterName", "Value")
.param("ParameterName", "Value")
.accept(MediaType.APPLICATION_JSON);
and the perfrom
mockMvc.perform(requestBuilders)
.andDo(print())
.andExpect(status().isOk())
.andReturn();

Related

Integration Testing Async controller

I am doing controller integration testing. A controller with a get mapping returns Flux.
#Slf4j
#RequiredArgsConstructor
#RequestMapping("journal")
public class EntryController {
private final SomeService someService;
#GetMapping
public Flux<MyEntity> getEntity(
#RequestParam(required = false) String documentId,
#RequestParam(required = false) String docNumber){
return someService.getEntities( GetEntriesRequest.builder()
.documentId(documentId)
.docNumber(docNumber).build;
}
#PostMapping
public MyEntity postNew(#RequestBody #Valid MyEntity entity) {
return someService.save(entity);
}
}
.
Initially, I tried to test it like this. (method asJson remakes the Entity created by creatingEntity method in a Json format). I'm already tested a controller with a post mapping and it works right.
#Test
void getEntriesByDocumentNumber() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(post("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJson(creatingEntity())))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andReturn();
String response = mvcResult.getResponse().getContentAsString();
String documentIdFromResponse =
JsonPath.parse(response).read("$.documentId");
this.mockMvc.perform(get("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.param("documentId", documentIdFromResponse))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk());
I do not know how to process the response that I receive. The fact is that the response body is empty, but the method works, this can be seen in the async result. I did not find how to get the asinc result. And I can’t use JsonPath, because the body is empty.
HTTP Method = GET
Request URI = /journal
Parameters = {documentId=[1590067372983-9ce4f563-520d-42ff-bd31-5b78befaf4b1]}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json"]
Body = null
Session Attrs = {}
Async:
Async started = true
Async result = [MyEntity(documentId=1590067372983-9ce4f563-520d-42ff-bd31-5b78befaf4b1, documentNumber=100)]
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I try to use WebTestClient, But this code does not work. It's falling with No bean named 'webHandler' available
#SpringBootTest
#AutoConfigureMockMvc
class ApplicationTests {
#Autowired
private MockMvc mockMvc;
WebTestClient webTestClient;
#BeforeEach
void setUp(ApplicationContext context) {
webTestClient = WebTestClient.bindToApplicationContext(context).build();
}
#Test
void getEntityTest() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(post("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJson(creatingEntity())))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andReturn();
String response = mvcResult.getResponse().getContentAsString();
String documentIdFromResponse = JsonPath.parse(response).read("$.documentId");
webTestClient.get()
.uri("journal/")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$[0].documentId").isEqualTo(documentIdFromResponse);
}
}
I'm already find this. But I don't know how to use it
#Bean
public WebHandler webHandler() {
//implement your bean initialization here
}

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.

Testing deleteAll() from repository with delete method rest api with MockMvc

I am doing the integration tests on a REST api where all the tests work but this one.
#Test
public void deleteAllUsers_should_return_noContent() throws Exception {
//Given
//When
ResultActions resultActions = mockMvc
.perform(delete("/pair?delAll"));
//Then
resultActions
.andDo(print())
.andExpect(status().isNoContent());
}
I am expecting a 204 http status but it gets a 400. Here is the code for the method:
#RequestMapping(value = "/pair", method = RequestMethod.DELETE, params = "delAll")
public ResponseEntity<Void> deleteAllUsers() {
userRepository.deleteAll();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
Any ideas to what am I doing wrong?
EDIT: Found the solution just adding "=true" to these lines
#RequestMapping(value = "/pair", method = RequestMethod.DELETE, params = "delAll=true")
ResultActions resultActions = mockMvc
.perform(delete("/pair?delAll=true"));

Getting httpServletRequest attribute with MockMvc

I have a really simple controller defined in this way:
#RequestMapping(value = "/api/test", method = RequestMethod.GET, produces = "application/json")
public #ResponseBody Object getObject(HttpServletRequest req, HttpServletResponse res) {
Object userId = req.getAttribute("userId");
if (userId == null){
res.setStatus(HttpStatus.BAD_REQUEST.value());
}
[....]
}
I tried to call using MockMvc in many different way but, I'm not able to provide the attribute "userId".
For instance, with this it doesn't work:
MockHttpSession mockHttpSession = new MockHttpSession();
mockHttpSession.setAttribute("userId", "TESTUSER");
mockMvc.perform(get("/api/test").session(mockHttpSession)).andExpect(status().is(200)).andReturn();
I also tried this, but without success:
MvcResult result = mockMvc.perform(get("/api/test").with(new RequestPostProcessor() {
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setParameter("userId", "testUserId");
request.setRemoteUser("TESTUSER");
return request;
}
})).andExpect(status().is(200)).andReturn();
In this case, I can set the RemoteUser but never the Attributes map on HttpServletRequest.
Any clue?
You add a request attribute by calling requestAttr ^^
mockMvc.perform(get("/api/test").requestAttr("userId", "testUserId")...
You could use
mvc.perform(post("/api/v1/...")
.with(request -> {
request.addHeader(HEADER_USERNAME_KEY, approver);
request.setAttribute("attrName", "attrValue");
return request;
})
.contentType(MediaType.APPLICATION_JSON)...
#ResponseStatus(HttpStatus.OK)
#GetMapping(Routes.VALIDATE_EMAIL_TOKEN + "/validate")
public String validateEmailToken(#RequestParam(value = "token") String token,
HttpServletRequest httpServletRequest) throws RestServiceException {
return credentionChangeService.getUserByToken(token, httpServletRequest);
}
//test method
#Mock
private HttpServletRequest httpServletRequest
#Mock
private MerchantCredentialsChangeService mockCredentionChangeService;
#Test
public void testValidateEmailToken() throws Exception {
final String token = "akfkldakkadjfiafkakflkd";
final String expectedUsername = "9841414141";
Mockito.when(mockCredentionChangeService.getUserByToken(Matchers.eq(token), Matchers.any(HttpServletRequest.class)))
.thenReturn(expectedUsername);
mockMvc.perform(get(Routes.VALIDATE_EMAIL_TOKEN + "/validate")
.param("token", token))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.content().string(expectedUsername));
}

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