This function is used to update the user details in the database. can someone help me to write test cases for this function.
#RequestMapping(value = "/updateDetails", method = RequestMethod.POST)
public String updateVendorDetails(#Valid #ModelAttribute("users") Users users, BindingResult result,Model model) {
logger.info("{}.{}",new VendorController().getClass().getPackageName(), new VendorController().getClass().getName());
if(result.hasErrors()) {
model.addAttribute("edit","edit");
logger.warn("Function: updateVendorDetails(), Information: Error while updating vendor details");
return register.toString();
}
userDao.updateVendorDetails(users);
logger.info("Function: updateVendorDetails(), Information: Vendor details updated successfully");
return vendor.toString();
}
Update
Code:
mockMvc.perform(post("/updateDetails").accept(MediaType.TEXT_HTML).params(params)).andExpect(status().isOk());
Resulting error:
This says that post method is forbidden and my test fails
This is my Test class
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class TestVendorPage {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
}
#WithMockUser(roles = "VENDOR")
#Test
public void testIfUpdateEdtailsIsAvailableOnlyForVendor() throws Exception {
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("firstName", "vinod");
params.add("lastName", "babu");
params.add("contactNumber", "9952016709");
mockMvc.perform(post("/updateDetails").accept(MediaType.TEXT_HTML).params(params)).andExpect(status().isOk());
}
}
Regarding your update:
Thank you for clarifying your post with a specific error/specific problem.
For that specific error - HTTP 403: Forbidden - this should resolve the problem:
Unit test Springboot MockMvc returns 403 Forbidden
i think probleam is happend in "mockMvc" object is not
autowired.mockMvc object should load from WebApplicationContext in
before program run.
Please - PLEASE - consider looking at one or more of the links I cited above.
baeldung.com: Testing in Spring Boot
spring.io: Testing the Web Layer
mkyong.com: Spring REST Integration Example
I've found all three sites very valuable resources. Time spent with these tutorials will help you a great deal!
Hello I am trying to create a dirty test for my soap integration test. I just got SSL working on my spring boot app and I wanted to see if it will hit my soap end point.
When I run man verify on my integration test I get this error:
com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/plain. Is this an error message instead of a SOAP response?
Here is my test code :
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {EndPointTestConfiguration.class
})
public class SoapIT {
private static ApplicationContext context;
#BeforeClass
static public void setup(){
SpringApplication springApplication = new SpringApplicationBuilder()
.sources(MockServerApp.class)
.build();
context = springApplication.run();
}
#Autowired
private String studyDetailDemo;
#Test
public void soapTest() throws ClientProtocolException, IOException {
String result = Request.Post("https://127.0.0.1:28443/nulogix/ws/billingtool")
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(studyDetailDemo, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
}
}
I am kind of new to integration testing and have no idea what this error means
Thank you for any help
I think you need to read up a bit on how to do spring testing.
testing-with-mock-environment
#SpringBootTest will automatically scan for spring annotated classes and load up a mockspringcontext for you so you dont need to do all the #BeforeClass things.
If you want to call this "Mock context" you need configure and autowire in a MockMvc, WebTestClient or TestRestTemplate.
On the other hand if you want to start a real server you need to specify #SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) (or a defined port).
You can read all about it in the linked documentation above.
And btw, you can't autowire in a string.
Your code should look something like this:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class SoapIT {
#LocalServerPort
private int port;
private String studyDetailDemo = "some body text";
#Test
public void soapTest() throws ClientProtocolException, IOException {
String result = Request.Post("https://127.0.0.1:" + port + "/nulogix/ws/billingtool")
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(studyDetailDemo, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
}
}
Havn't tried the code, wrote it on mobile.
This is not a duplicate referenced question, because it is Spring specific. Whoever added that (3 years after the fact!) didn't bother to read the question or comment thread to see what the real answer was. The accepted answer isn't quite the answer, but the author of the answer never came back and edited it like I asked.
Given the restful method below, Spring 3.1 gives a 400 error with "The request sent by the client was syntactically incorrect ()." when the token parameter contains a URL encoded slash (%2F), for example "https://somewhere.com/ws/stuff/lookup/resourceId/287559/token/R4o6lI%2FbBx43/userName/jim" Without the %2F everything works fine. A 3rd party is already calling this service (of course!) so I can't change what they send, in the short term at least. Any ideas on how to work around this on the server side?
This problem is described very well here https://jira.springsource.org/browse/SPR-8662 though that issue is related to UriTemplate which I am not using that I can tell.
#RequestMapping("/ws/stuff/**")
#Controller
public class StuffController {
#RequestMapping(value = "/ws/stuff/lookup/resourceId/{resourceId}/token/{token}/userName/{userName}", method = RequestMethod.GET)
public #ResponseBody
String provisionResource(#PathVariable("resourceId") String resourceId, #PathVariable("token") String token, #PathVariable("userName") String userName, ModelMap modelMap,
HttpServletRequest request, HttpServletResponse response) {
return handle(resourceId, userName, request, token, modelMap);
}
}
Note: This is on Glassfish 3.1.2, and at first it was Grizzly/Glassfish not accepting the slash, but
-Dcom.sun.grizzly.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
fixed that.
asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-2.http.encoded-slash-enabled=true
didn't seem to help.
for spring-boot, the following did the trick
#SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
This could be your answer: urlencoded Forward slash is breaking URL
I would suggest not putting that in the path, move it to a request param instead.
Work around:
You could change the RequestMapping to
#RequestMapping(value = "/ws/stuff/lookup/resourceId/**", method = RequestMethod.GET)
and then parse the path variables manually from the request object.
2019 Update for Spring Boot 2+ / Spring (Security) 5+ / Java 8+:
As my edit to iamiddy's answer was rejected I want to also provide the complete solution for Spring Boot 2 + as an separate answer.
The WebMvcConfigurerAdapter is deprecated with Spring5 / Java8 and can be replaced directly with the Interface WebMvcConfigurer ending up with:
#SpringBootApplication
public class Application extends WebMvcConfigurer {
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
Plus you also need to configure Spring's (Strict)HttpFirewall to avoid the blocking of encoded slashes with the error message The request was rejected because the URL contained a potentially malicious String "%2F"
#Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowUrlEncodedSlash(true);
return firewall;
}
Spring Boot will use the above HttpFirewall Bean when available - otherwise it might be necessary to configure the WebSecurity as mentioned here:
For spring boot application this worked for me..
Version 1
Add
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
to your application.properties file
Version 2
run your spring boot application like this.
static void main(String[] args) {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run this, args
}
Version 3 or run your java application with
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
This fixed %2F encoded slash path variable for me.
Here is a fix for Spring 3.2.4 (should work for other versions as well). One must overwrite the default UrlPathHelper
public class UrlPathHelperFixed extends UrlPathHelper {
public UrlPathHelperFixed() {
super.setUrlDecode(false);
}
#Override
public void setUrlDecode(boolean urlDecode) {
if (urlDecode) {
throw new IllegalArgumentException("Handler [" + UrlPathHelperFixed.class.getName() + "] does not support URL decoding.");
}
}
#Override
public String getServletPath(HttpServletRequest request) {
return getOriginatingServletPath(request);
}
#Override
public String getOriginatingServletPath(HttpServletRequest request) {
return request.getRequestURI().substring(request.getContextPath().length());
}
}
And inject it to the Mapping Handler:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="order" value="-1"></property>
<property name="urlPathHelper">
<bean class="com.yoochoose.frontend.spring.UrlPathHelperFixed"/>
</property>
</bean>
After a day of hard works it works now for me :-)
It was suggested to Spring team as https://jira.springsource.org/browse/SPR-11101
I have found this solution which is working for me;
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
just before
springApplication.run(args);
and add below code in Application class
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
We just ran into this issue at my office, we did what was suggestion above from what Solubris said where you put it in a query param. The only additional requirement is that the data could have an '&' as well, which would mess up the query param. All we had to do is encode the text before it is sent in the URL and even '&' were filtered out.
Another answer would be to encode "/" twice, which would produce "%252F". In your mapped endpoint, Spring will decode it back to "%2F". All you need more is to decode it one more time using something like this:
URLDecoder.decode(encoded_URL, "UTF-8");
The following resolved the BACK_SLASH issue:
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
But, same functionality could be done via application.yml.
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true
This setting doesn't work. I did not find a way for that, and still looking at it.
In order to avoid parsing the variables manually I did the following:
Add the following before executing any other code:
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
And in the controller, add 2 variables instead one, for example:
#RequestMapping(value = "/api/devices-by-name/device={deviceId}/restconf/data/ietf-interfaces:interfaces-state/interface={dpuIdPrefix}/{dpuIdSuffix}",
method = RequestMethod.GET,
produces = "application/json")
public ResponseEntity<String> getInterfaceState(#PathVariable(value = "deviceId") String deviceId,
#PathVariable(value = "dpuIdPrefix") String dpuIdPrefix,
#PathVariable(value = "dpuIdSuffix") String dpuIdSuffix) {
String dpuId = dpuIdPrefix + "/" + dpuIdSuffix;
And with that I can retrieve the following:
curl -s -X GET http://localhost:9090/api/devices-by-name/device=ZNSDX16DPU03/restconf/data/ietf-interfaces:interfaces-state/interface=gfast%200%2F14
If the slash is optional, then you might need to configure two different request mappings.
I have my project with SpringBoot 1.5.1 gradle.
I need to response with pdf file with "OK" or some other statuses.
So problem is when I request with "Postman" code invokes 2 times.
when I request with "curl" code invokes 1 time.
Obviously I want to invoke it 1 time.
I have an application class with:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And my controller with:
#RequestMapping(value = "/report/{reportTemplate:.+}", method = POST)
#ResponseBody
public ResponseEntity createReport(HttpEntity<List<ParametersEntity>> httpEntity,
#PathVariable String reportTemplate) throws IOException {
byte[] data = ...;// my data
return ResponseEntity
.ok()
.contentLength(data.length)
.contentType(MediaType.APPLICATION_PDF)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=output.pdf")
.contentType(MediaType.parseMediaType(MediaType.APPLICATION_PDF_VALUE))
.body(data);
}
createReport is in #RestController class.
Also I have application.properties file in my src/main/resources/
server.port: 10500
management.port: 10501
management.address: 127.0.0.1
Your code looks OK. Nothing wrong with it.
If you are in DEBUG mode when invoking the request from the POSTMAN it may confuse it and send the request for a second time. I gues it depends on some configurations. But while you have no problems with CURL you must search the problem in POSTMAN probably not your code.
To test our API that connects to the facebook graph API we use a mock server setup based on Jersey Test Framework and grizzly:
#Path("/" + PostRest.RESOURCE)
#Produces("application/json")
public class PostRest {
public static final String RESOURCE = "111_222";
#GET
public Response getPost(#QueryParam("access_token") String access_token) {
if (access_token != VALID_TOKEN) {
return Response.status(400).entity(createErrorJson()).build();
}
return Response.status(200).entity(createSomeJsonString()).build();
}
Now while I can react to an invalid or missing access_token with the correct error response, I also want to test that my API reacts correctly when trying to access an unkown resource at facebook ie an unkown path.
Right now I get a 404 from my grizzly obviously, if I try to access say "/111_2", but facebook seems to catch that error and wrap it inside a Json response, containing the string "false" with status 200.
So... How do I set up the Test Framework to return
Response.status(200).entity("false").build();
every time it is called for an known path?
Basic example:
#ContextConfiguration({ "classpath:context-test.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
public class SomeTest extends JerseyTest {
#Inject
private SomeConnection connection;
private String unkownId = "something";
public SomeTest() throws Exception {
super("jsonp", "", "com.packagename.something");
}
#Test(expected = NotFoundException.class)
public void testUnkownObjectResponse() throws NotFoundException {
// here it should NOT result in a 404 but a JSON wrapped error response
// which will be handled by the Connection class and
// result in a custom exception
connection.getObject(unkownId);
}
Or maybe I can set up grizzly to behave as desired..?!
Thanks!
Obviously facebook has it own service to intercept errors. Same thing should be done in your code. Just expose you own test service that intercepts all request
#Path("/test/errorTrap")
public class ErrorTrapService{
....
}
This service will produce any response you want. So any un-existing pages like http://mytest/test/errorTrap/111_2 will be intercepted by test service and produce expected response for you