Am trying the reuse the restassured get call in the testng api tests, but the restassured instance in using the cookies received from the previous response.
Tried RestAssured.reset(); but this doesn't help in flushing the cookies we got from earlier request/response.
Reason for this question - As the get endpoint behaves differently if there is a session cookie exist on the request.
#Test // TestNG test
public void test_1(){
//Set Cookie
Cookie cookie = new Cookie.Builder("COOKIENAME","COOKIEVALUE").setDomain("*.com").setPath("/").setExpiryDate(SOMELATERDATE).build();
RestAssured.baseURI = https://ENV_URL;
Response response = RestAssured.given().log().all()
.cookies(new Cookies(cookie)).when().get("/END_POINT").then().extract().response().prettyPeek();
RestAssured.reset();
}
#Test // TestNG test
public void test_2(){
//Set Cookie
Cookie cookie = new Cookie.Builder("COOKIENAME", "COOKIEVALUE").setDomain("*.com").setPath("/").setExpiryDate(SOMELATERDATE).build();
RestAssured.baseURI = https://ENV_URL;
// Still Reuses the cookie received from previous response
Response response = RestAssured.given().log().all()
.cookies(new Cookies(cookie)).when().get("/END_POINT").then().extract().response().prettyPeek();
RestAssured.reset();
}
Use CookieFilter. If you want to exclude the a particular cookie you can use the following code.
#Test
public void sampletest(){
CookieFilter cookieFilter = new CookieFilter();
Response response = RestAssured.given().
cookie("foo", "bar").
filter(cookieFilter). // Reuse the same cookie filter
// if "foo" is stored in cookieFilter it won't be applied because it's already applied explicitly
expect().
statusCode(200).
when().
get("/y");
}
Related
I am testing an application written with Java and Spring Boot and I have a question.
My test simulates an HTTP request which is valid only if the customData data is placed inside the Cookie header.
This is the code for my simple test:
#Test
public void myFristTest() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post(MY_URL)
.header("Cookie", "customData=customString")
.accept(MediaType.APPLICATION_JSON_VALUE)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(ConversionUtil.objectToString(BODY_OF_MY_REQUEST)))
.andExpect(status().isCreated());
}
Unfortunately this test fails. The Java code that goes to test is the following:
String customData;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("customData")) {
customData = cookie.getValue();
}
}
}
if(customData != null) {
// code that returns HTTP status isCreated
} else {
throw new HttpServerErrorException(HttpStatus.FOUND, "Error 302");
}
In practice, it seems that the customData string, which should be taken from the request header Cookie, is not found! So the test only evaluates the else branch and actually also in the stacktrace tells me that the test was expecting the status isCreated but the status 302 is given.
How can this be explained, since the application (without test) works? I imagine that .header("Cookie", "customData=customString") in my test doesn't do what I want, that is, it doesn't set the header cookie correctly, which is why my method fails. How do I do a proper test that really inserts Cookie header into the request?
I use Junit 4.
The MockHttpServletRequestBuilder class provides the cookie builder method to add cookies. The MockHttpServletRequest created internally for the test ignores "Cookie" headers added through the header method.
So create a Cookie and add it
Cookie cookie = new Cookie("customData", "customString");
mockMvc.perform(MockMvcRequestBuilders.post(MY_URL)
.cookie(cookie)
.accept(MediaType.APPLICATION_JSON_VALUE)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(ConversionUtil.objectToString(BODY_OF_MY_REQUEST)))
.andExpect(status().isCreated());
I was trying to build a RESTful web service using Jersey.
In my server side code, there is a path with name "domain" which I use to display content. The content of the page the "domain" refers to is accessible only correct username and password are input.
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("domain")
public ArrayList<String> domainList(#Context HttpServletRequest req) throws Exception{
Environments environments = new DefaultConfigurationBuilder().build();
final ALMProfile profile = new ALMProfile();
profile.setUrl(environments.getAutomation().getAlmProfile().getUrl());
profile.setUsername((String) req.getSession().getAttribute("username"));
//Set username from input, HTML form
profile.setPassword((String) req.getSession().getAttribute("password"));
//Set password from input, HTML form
try (ALMConnection connection = new ALMConnection(profile);) {
if (connection.getOtaConnector().connected()) {
Multimap<String, String> domain = connection.getDomains();
ArrayList<String> domain_names = new ArrayList<String>();
for(String key : domain.keys()){
if(domain_names.contains(key)) domain_names.add(key);
}
return domain_names; //return the content
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
When I attempted to test if correct content was returned, I got an error (status=405, reason=Method Not Allowed). Below is my client side test.
public static void main(String[] args){
Environments environments = new DefaultConfigurationBuilder().build();
final ALMProfile profile = new ALMProfile();
profile.setUrl(environments.getAutomation().getAlmProfile().getUrl());
profile.setUsername("username"); //Creating a profile with username and password
profile.setPassword("password");
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI());
String response = target.path("domain").request().accept
(MediaType.APPLICATION_JSON).get(Response.class).toString();
//Above is the GET method I see from an example,
//probably is the reason why 405 error comes from.
System.out.println(response);
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/qa-automation-console").build();
}
The servlet configuration is good. We have other paths succesfully running.
I suspect the reason might come from I used a GET method to do the job that is supposed to be POST.
But I am not familiar to Jersey methods I can use.
Does anyone know any methods that I can use to test the functionality?
See 405 Status Code
405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
Your endpoint is for a #POST request. In your client you are trying to get().
See the Client API documentation for information on how to make a POST request. If it is supposed to be a GET request, then simply change the method annotation to #GET.
Also note, for your #POST resource methods, you should always put a #Consumes annotation with the media types the method supports. If the client send a media type not supported, then they will get a 415 not supported as expected. I would have posted an example of the client post, but I have no idea what type are you are expecting because of the missing annotation, also you don't even have a post object as a method parameter so I am not even sure if your method is really even supposed to be for POST.
See Also:
How to send json object from REST client using javax.ws.rs.client.WebTarget
I have a jax-rs endpoint. The purpose of the endpoint is to authorize a user. I need to login details inside a cookie. Below I have mentioned the related part of my code.
public Response authorize(#Context HttpServletRequest request) throws URISyntaxException {
if (authnResult.isAuthenticated()) {
//TODO create a cookie to maintain login state
Cookie authCookie = new Cookie(FrameworkConstants.COMMONAUTH_COOKIE, "test");
authCookie.setSecure(true);
authCookie.setHttpOnly(false);
authCookie.setMaxAge(5 * 60);
}
EDIT:
This is my first time when creating cookies. I followed some tutorials. In these tutorials it has added the created cookie to the response. But inside the endpoint I can't access the response. So how can I create the cookie? Please advice me.
Updated code:
public Response authorize(#Context HttpServletRequest request) throws URISyntaxException {
NewCookie cookie = new NewCookie("CookieName","CookieValue");
Response.ResponseBuilder builder = Response.ok("Cool Stuff");
builder.cookie(cookie);
Response response=builder.build();
Cookie[] cookies = request.getCookies();
}
what I need to know is how to access the newly created cookie.
You can create a javax.ws.rs.core.NewCookie. There are a bunch of different constructors, just go through the API docs.
Then you can add cookies through ResponseBuilder#cookie(NewCookie). So for example:
#GET
public Response getCookie() {
NewCookie cookie = new NewCookie("Name", "Value", "path", "domain",
"comment", 300, true, true);
ResponseBuilder builder = Response.ok("Cool Stuff");
builder.cookie(cookie);
return builder.build();
}
UPDATE (with complete example)
#Path("cookie")
public class CookieResource {
#GET
public Response getCookie(#CookieParam("A-Cookie") String cookie) {
Response response = null;
if (cookie == null) {
response = Response.ok("A-Cookie: Cookie #1")
.cookie(new NewCookie("A-Cookie", "Cookie #1"))
.build();
return response;
} else {
String cookieNum = cookie.substring(cookie.indexOf("#") + 1);
int number = Integer.parseInt(cookieNum);
number++;
String updatedCookie = "Cookie #" + number;
response = Response.ok("A-Cookie: " + updatedCookie)
.cookie(new NewCookie("A-Cookie", updatedCookie))
.build();
return response;
}
}
}
After 38 requests, you can see the result. I used a Firefox plugin Firebug. You can see the sent cookie #37, and returned cookie #38
If you need help trying to access the cookie from the client (as suggested in your comment), that may be suitable for another question on SO. Maybe off topic for this discussion, as it will rely on another technology. If this is not what you are looking for, then maybe a better explanation of exactly what you are trying to accomplish would help.
I have a scenario where I want to store session information across multiple sessions in Application # 2. We have two applications deployed on a tomcat server. Our use case is as follows:
A. Web Application # 1 makes a HTTP Post request to Application # 2 using a HTTP Rest Client. POST request contains a JSON http request body encapsulating the data to be send to Application # 2. The code block is as follows:
RestTemplate template = new RestTemplate();
final SearchCustomer customer = new SearchCustomer();
restTemplate.execute(
SEND_CUSTOMER_PROFILE, HttpMethod.POST,
new SearchRequestCallback(searchCustomer), null);
The request callback function is
static class SearchRequestCallback implements RequestCallback {
/**
* Write a JSON response to the request body.
*/
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
HttpHeaders httpHeaders = request.getHeaders();
List<MediaType> acceptableMediaTypes = new LinkedList<>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptableMediaTypes);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
request.getBody().write(
new Gson().toJson(this.searchCustomer).getBytes(StandardCharsets.UTF_8.displayName()));
}
}
The second application has a Spring controller with the following set up
#Controller
public class SearchCustomerController {
/**
* Builds customer profile knowledge graph.
*
* <p>This is invoked as an synchronous request.
*/
#RequestMapping(value="/searchProfilePayload.go", method=RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void constructSearchCustomerProfileKnowledgeGraph(
#RequestBody final SearchCustomer customer, HttpServletRequest request) {
UserContext userContext =
(UserContext) request.getSession().getAttribute("userContext");
if (userContext == null) {
// Perform heavy operation to fetch user session.
userContext = UserContextHelper.getUserContext(request);
request.getSession("userContext", userContext)
}
userContext.setCustomerProfile(customer);
}
}
When I make a call to another URI within the application # 2 say via browser, I want it done in such as way that the session attributes are retained when making this call. Is there a way to do that?
I know about URL rewriting that stores JSESSIONIDin the cookie, but I don't think how you can set the value when making a rest call, and using the same JESSIONID to maintain session attributes.
Is there a better way to do this? These have no answers. I have looked at these links, but none seem to answer my question.
HTTP and Sessions
comparison of ways to maintain state
jraahhali is spot on.
Set the cookie header with the value of JSESSIONID=${sessionId} or use it directly in the url as per the URL rewriting link.
First step is to retrieve the JSESSIONID from the initial response (this will depend on how you decide to set the session id - URL or Cookies, lets assume by cookie for now)
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
HttpHeaders httpHeaders = request.getHeaders();
List<MediaType> acceptableMediaTypes = new LinkedList<>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptableMediaTypes);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
request.getBody().write(
new Gson().toJson(this.searchCustomer).getBytes(StandardCharsets.UTF_8.displayName()));
ClientHttpResponse response = request.execute();
String sessionId = response.getHeaders().get(HttpHeaders.SET_COOKIE).split(":")[1].trim(); // I didnt test this, will prolly get a NPE :P
this.sessionId = sessionId;
}
Then in subsequent requests (ie from the app #1 or a browser or whatever)
if (this.sessionId != null && !this.sessionId.equals(""))
httpHeaders.set(HttpHeaders.COOKIE, "JSESSIONID=" + this.sessionId);
// ...
request.execute();
Note if you really want to use a browser as the other client then I would use the URL rewriting method for ease of use ...
A test case for my contact formular page is to make sure it's always in a secure context respectively using SSL. Basically, all I want to know, is that I have a given request where request.secure = true;
The following response does not contain any information about this and its headers are empty:
#Test
public void shouldShowContactForm() {
Response response = GET("/contact");
// How can I ask the response, if the complete URL is in HTTPS?
}
Even if I explicitly set my own request, I cant see the right way to do this:
#Test
public void shouldShowContactFormInSSLContext() {
Request request = newRequest();
request.secure = true;
Response response = GET(request, "/contact");
// Is it now possible?
}
Is this even the right approach to test this or am I simply missing something important about the request/response?
For this question I think what I've done for my apps in the past is have a #before interceptor on all my controllers that looks like this.
#Before
static void checkSSL(){
if(Play.mode.equals(Play.Mode.PROD)){
if(!request.secure) {
Router.ActionDefinition cashTicketDefinition = Router.reverse(request.controller + "." + request.actionMethod);
cashTicketDefinition.absolute();
String url = cashTicketDefinition.url.replaceFirst( "http:", "https:");
redirect(url, true);
}
}
}