How to store id generated by post rest assured - spring-boot

I'm trying to get the id generated when I make the post and use it in the future (maybe when testing the delete), but I'm not getting it.
My method that tests POST:
#Test
public void givenData_WhenPost_Then200() throws Exception {
String path = given()
.body("{\r\n"
+ " \"nome\":\"teste\",\r\n"
+ " \"valor\": 2.5\r\n"
+ "}")
.contentType(ContentType.JSON)
.when()
.post("/acessorios")
.then()
.log().all()
.assertThat()
.statusCode(200).extract().jsonPath().getString("nome");
System.out.println(path);
}
This code returns:
Failed to parse the JSON document.
And at last: is possible to use the id generate in others methods even its not global?

If you'd like to use id from response in other tests, you can create static field id in the test class and assign value of response.jsonPath.getString("id");

The first thing you need to do is to make sure response is actually in json format.
You can add accept header in your chain of methods like:
String path = given()
.body("{\r\n"
+ " \"nome\":\"teste\",\r\n"
+ " \"valor\": 2.5\r\n"
+ "}")
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.when()
.post("/acessorios")
.then()
.log().all()
.assertThat()
.statusCode(200).extract().jsonPath().getString("$.id");

Related

patch endpoint test using rest assured mock mvc

I am trying to write a test for patch end point using rest assured mock mvc.
But i am not able to create an object of jsonmerge patch to place in the body of the mock.below is the end point for which i need to wrote the test
#PatchMapping(path = "/{orderId}", consumes = "application/merge-patch+json")
public OrderDTO updateOrder(#PathVariable Long orderId, #RequestBody
JsonMergePatchImpl patchRequest){
return facade.patchOrder(orderId,patchRequest);
}
and following is what i'm trying but not able to figure out
Mockito.when(facade.patchOrder(any(),any())).thenReturn(orderDTO);
OrderDTO actual=given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body()
.accept("application/merge-patch+json")
.when()
.patch(BASE_URL+"/"+1l)
.then()
.assertThat()
.statusCode(200).extract().as(OrderDTO.class);
My problem is i am not able to create an object for jsonmerge patch , and what to put in as content type
You can specify contentType as String:
.contentType("application/merge-patch+json")

webflux Mono response empty

I have a very simple spring webflux rest endpoint in my project.
#Bean
public RouterFunction authRoute() {
return RouterFunctions.route(POST("/auth/signin").and(accept(APPLICATION_JSON)), this::signIn)
.andRoute(POST("/auth/signup").and(accept(APPLICATION_JSON)), this::signUp)
.andRoute(POST("/auth/test").and(accept(APPLICATION_JSON)), this::test);
}
And /auth/test endpoint just reply back with the username supplied.
public Mono<ServerResponse> test(ServerRequest request) {
System.out.println("Start test ");
Mono<JwtRequest> jwtRequestMono = request.bodyToMono(JwtRequest.class);
jwtRequestMono.subscribe(v -> System.out.println(v.getUsername() + ":" + v.getPassword()));
return jwtRequestMono
.flatMap(j -> ServerResponse.ok().contentType(APPLICATION_JSON).bodyValue(j.getUsername()));
}
The problem I am facing is that the response body is empty, it should be the username. I also verified that when I return the hardcoded string, it passes. It fails when I depend on jwtRequestMono.flatMap(...
This line is almost certainly your downfall:
jwtRequestMono.subscribe(v -> System.out.println(v.getUsername() + ":" + v.getPassword()));
Your request can't be subscribed to multiple times - so you subscribe to it on this line (which works and prints out the values as expected), then the framework subscribes to it, and it blows up. I'd expect to see an exception and a 500 response returned when this happens by default, so chances are you're swallowing an exception somewhere.
Never subscribe within your own application. That's the frameworks job.
Instead, if you want to have a "side-effect" where you print the values as they come in, then use doOnNext() as part of your reactive chain:
return jwtRequestMono
.doOnNext(v -> System.out.println(v.getUsername() + ":" + v.getPassword()))
.flatMap(j -> ServerResponse.ok().contentType(APPLICATION_JSON).bodyValue(j.getUsername()));

How to validate json response in bean shell and perform some action in case the response is not as expected in jmeter?

I want to extract the json response in jmeter and if the response is not as expected, i need to print it to a csv file.
i tried using the contains method to check if the response contains an expected keyword but it doesn't seem to work. Is there anyother way I can do this?
Sample Code here:
log.info(ctx.getPreviousResult().getResponseDataAsString());
r = ctx.getPreviousResult().getResponseCode();
d = ctx.getPreviousResult().getResponseDataAsString();
if(!d.contains("valid")){
p.println(r +","+ vars.get("email") +",");
}
This is my json response
{
"isBlueLinkServicePinValid": "valid"
}
I'm checking for the keyword "valid"
if(!d.contains("valid"))
But it doesn't seem to work?
TIA
Since JMeter 3.1 it is not recommended to use Beanshell for scripting, you should go for JSR223 Test Elements and Groovy language instead. The main reason is that Groovy has much better performance than Beanshell does.
Groovy has built-in JSON support therefore you can extract isBlueLinkServicePinValid attribute value in an easy way:
String response = prev.getResponseDataAsString();
log.info("Response: " + response)
String valid = new groovy.json.JsonSlurper().parseText(response).isBlueLinkServicePinValid
log.info("Valid: " + valid);
if (valid.equals("valid")) {
log.info("Do something");
}
else {
log.info("Do something else");
}
Demo:

RestAssured testing, get user token

What I want to do: I want to test my endpoint using RestAssured. The key is that the endpoint is available only for users who are logged in. For logging in I'm using spring security default endpoint with custom successHandler in which I'm setting some random token, saving it to database and returning in header "User-Token". I'm not creating a session on the back end. When I want to access a secured endpoint, front-end makes a call to it, with "User-Token" header. Then I'm using the token for checking in the database. Each token is different and random. Also I don't use any spring-security things for token. Now I want to test this behavior.
Technologies: React & Redux, Spring Boot, RestAssured, JUnit, Tomcat
What's not working: First of all, I'm not really sure how to obtain the token. I mean I can force it by hand to database to some test user, but AFAIK it's a bad bad practice. I read the documentation and come across part about auth().form. But below it was mentioned that it's not the best approach as have to made to the server in order to retrieve the webpage with the login details and it's not possible - webpage is totally separated from backend. I did try the approach nevertheless but it didn't work.
#Before
public void LogInUser(){
String loginUrl = "http://localhost:8080/login";
userToken =
given().auth().form("username","password").
when().get(loginUrl).getHeader("User-Token");
System.out.println(userToken);
}
So then I thought that maybe I don't need auth() at all - I don't need session, so calling the endpoint itself with data should be enough. I checked how data is passed from front-end to back-end and did this:
Form Data: username=something&password=something
#Before
public void LogInUser(){
String loginUrl = "http://localhost:8080/login";
userToken =
given().parameter("username=oliwka&password=jakies")
.when().get(loginUrl).getHeader("User-Token");
System.out.println(userToken);
}
And while it's passing, userToken is null. It's declared as class variable not method variable and it's String.
How can I obtain token for user and test my endpoint for which I need a token?
You can use below procedure to get the access token.
Step 1 : Create a method that will accept a json string and parse the data and return the access token. below is the method. You can use your preferable json parser library.
public String getAccessToken(String jsonStr) {
JSONParser parser = new JSONParser();
Object obj = null;
try {
obj = parser.parse(jsonStr);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject jsonObject = (JSONObject) obj;
String accessToken = (String) jsonObject.get("access_token");
System.out.println("access_token : " + accessToken);
return accessToken;
}
Step 2 : Now call your login api with username and password like below
String loginUrl = "http://localhost:8080/login";
Response res = null;
String returnValue = "";
response = given().param("username", "yourUserName")
.param("password", "yourpassword")
.param("client_id", "If Any otherwise skip it")
.param("grant_type", "If Any otherwise skip it")
.param("clear_all", "true")
.post(loginUrl);
returnValue = response.body().asString();
String accessToken = getAccessToken(returnValue);
Please let me know if you can get your desired access token.

Fetching Form-data in spring controller

Hi It might look like duplicate but its not.
I am building a rest api using spring boot and need to fetch form-data sent by client app in POST request.
for testing purpose I am using postman. So far i have tried below
#PostMapping("/feed/comment/add/{feedId}")
public ResponseEntity<BaseResponse> addComment(#RequestHeader(name = Constants.USER_ID_HEADER) int userId,
#PathVariable("feedId") int feedId,
#RequestParam("comment") String comment
) {
LOGGER.info("Received add comment request with comment:"+comment);
return new ResponseEntity<BaseResponse>(new BaseResponse("You are not feed owner", RESPONSETYPE.ERROR), HttpStatus.UNAUTHORIZED);
}
this gives error "Required String parameter 'comment' is not present"
Second way tried:
#PostMapping("/feed/comment/add/{feedId}")
public ResponseEntity<BaseResponse> addComment(#RequestHeader(name = Constants.USER_ID_HEADER) int userId,
#PathVariable("feedId") int feedId,
#RequestParam Map<String, String> values
) {
for(String key: values.keySet()) {
System.out.println(key+":"+values.get(key));
}
return new ResponseEntity<BaseResponse>(new BaseResponse("You are not feed owner", RESPONSETYPE.ERROR), HttpStatus.UNAUTHORIZED);
}
this gives wired output:
------WebKitFormBoundarymk97RU1BbJyR0m3F
Content-Disposition: form-data; name:"comment"
test comment
------WebKitFormBoundarymk97RU1BbJyR0m3F--
I'm pretty sure that with plane servlet i can access this using request.getParameter("comment")
not sure how i can fetch it in case of spring rest controller.
"Required String parameter 'comment' is not present" this error happens when this paremeter is required but you didn't send it.
#RequestParam(value="comment", required=false)
this will make the comment parameter optional. So if you missed sending the comment parameter its ok.

Resources