I'm trying to test a method with this signature:
#RequestMapping(value="/Employee/{id}", method=RequestMethod.PUT, consumes="application/json")
#Transactional
public #ResponseBody Map update(#PathVariable Integer id,
#RequestBody HashMap<String, Object> information) {
}
The problem is that MockMvc param attributes accept only String parameters, is there a way to pass a HashMap or an instance class object to the RequestBody as parameter?
When I try to pass a HashMap as a string, I get a MismatchException.
You need to use Jackson for this. The idea is to deserialize your objects (doesn't matter that it's HashMap) into JSON string and pass it into MockMvc.
Here is tutorial how to do that. Just search for TestClass there and take a look how it is used. Skip the unit testing of GET requests.
Related
Im have #RestController and this method. how can I get any json and then select the handler depending on the method and pass it there for processing
PS. I use GSON instead of JACKSON
You can use #RequestBody in your method and take a String parameter:
public AbstractJsonResponse(#PaqthVariable String method, #RequestBody String json) {
...
}
See here: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html
Mainly the part that says:
Annotation indicating a method parameter should be bound to the body of the web request
how to validate map as #RequestParam in spring controller
public class Controller {
#RequestMapping(value="/")
public ModelAndView requestMethod(#RequestParam Map<String, String> mapParam){
////some stuff here
};
First of All you should send Map as RequestBody not as RequestParam.
You should create request DTO object instead of Map, to validate the Map you need to traverse and validate each key individually but using DTO you can directly validate using #Valid with your #RequestBody.
Refer this link for #Valid related code : https://www.baeldung.com/spring-boot-bean-validation
Send the parameters to server(spring framework) via get request, i am thinking of making a json object of all those parameters and send in get request so that in java spring i can recieve at as a map at the controller class in spring , how to achieve this
I am new to spring please help me out
I so far tried to send those parameters singly like(pram1,param2,param3,param4)
and recieve at the server side as string by setting param to string in type script before making get request to the server->i recieved parameters as map in controller
but i dont think it is a best way
{
param1: "param1"
param2: "param2
paramn: "paramn"
}
Send the above to server in the controller class ↓
#RequestParam MultiValueMap<String, String> requestMap
I want to recieve parameters as
String param1= requestMap.get("param1");
String param2=requestMap.get("param2");
If map type was an object it would be great so that i can recive any kind of object
example
at client side i am sending {param1: "myName", id: 0001}
at server side requestMap.get("param1"); requestMap.get("id");
As suggested by chrylis there's no need to manually extract parameters you can define a DTO/Request/POJO class, and Spring will map it automatically.
public class SampleDTO{
private String param1;
private String param2;
.
.
//getters and setters
}
if you specify RequestParam as hashmap, it gets automatically converted from json by jackson. Alternatively, if you are using String as the param, you can use ObjectMapper to convert it to a Map and get values from there.
You can map your incoming json to a Hashmap like so
#RequestMapping(method = RequestMethod.GET)
public String yourMethod(#RequestParam Map<String, String> parameters) {
String name = parameters.get("A"); //If your URL is http://test.com?A=ABC
...
}
I'm using MockMvc to test a method on my controller. But that controller method, as designed, expects a certain attribute to have been added to the model already, which would be the case in normal use. But when testing just this method, I can't figure out how to add the attribute to the model.
For example:
#RequestMapping(value = 'myEndpoint', method = RequestMethod.POST)
public String IWantToBeTested(Model model, #RequestParam(myParam) String paramValue) {
String needThis = model.asMap().get("NeedThisAttributeSetAlready");
String newThing = needThis + myParam;
model.AddAttribute("NewThing", newThing);
}
when I run the test with MockMvc, it supplies an empty model to this function, and I get an null pointer exception.
My test looks like this:
mockMvc.perform(post("/myEndpoint")
.param("myParam", "howdy")
.contentType("application/x-www-form-urlencoded"))
.andExpect(model().attributeExists("NewThing"))
.andExpect(model().attribute("NewThing", "oldThinghowdy"));
I've tried
#Mock
Model model;
but I don't know what to use for when().thenReturn(), because there aren't any get methods on the Model interface in Spring Boot, so I don't know what to mock. I tried:
when(model.asMap()).thenReturn(mockModel.asMap());
where mockModel is a static in my test class and has "NeedThisAttributeSetAlready" in it. That didn't work.
Any ideas?
I'm trying to use the #InitBind annotation to map only certain fields on the object in the request body.
I have a spring controller defined in this way:
#RequestMapping(value = "addAddress", method = RequestMethod.POST)
public Object addAddressToPerson(
HttpServletRequest request,
HttpServletResponse res,
#RequestParam(value = "name", required = false) String name,
#RequestParam(value = "surname", required = false) String surname,
#RequestBody personDTO personJson,BindingResult result) {
The client request will be a a json representing a personDTO, but I don't want that field except the address to be mapped in the object for security reasons.
The input will be something like:
{ "address":"123 Street","........}
The personDTO contains many fields, and since spring map all of them directly in a DTO, that can be a problem.
I've seen that a solution is to use a Binder to declase the allowed or Disallowed field, but if I check the personDTO inside the controller, other fields are populate (for example if pass "id":"1234").
Any Hints?
The binder code is the following:
#InitBinder("orderJson")
protected void orderJsonBinder(WebDataBinder binder){
binder.setAllowedFields(new String[]{"address"});
}
Am I missing something?
Best Regards,
Luca.
But you are not binding request parameters to a model attribute bean, you are just asking spring to use an appropriate MessageConverter to convert the request body. As you say it is Json, you will use a MappingJackson2HttpMessageConverter (or MappingJacksonHttpMessageConverter with Jackson 1.x). The Spring Reference Manual says for this converter :
[This is an] HttpMessageConverter implementation that can read and write JSON using Jackson's ObjectMapper. JSON mapping can be customized as needed through the use of Jackson's provided annotations. When further control is needed, a custom ObjectMapper can be injected through the ObjectMapper property for cases where custom JSON serializers/deserializers need to be provided for specific types. By default this converter supports (application/json).
#InitBinder can only configure binding of #ModelAttribute annotated parameters. It is useless here. If Jackson annotations are not enough, you will have to use a custom object mapper.
And I am surprised that you can use a BindingResult after a #RequestBody parameter, because the documentation says that it should follow a #ModelAttribute one.