Springboot Mockito : Mocked service method returning empty body - spring

I have the following jersey controller.
#POST
#ApiOperation(value = "", response = Certification.class)
public Response addCertification(#Valid CertificationRequest request) {
return Response.ok(certificationService.addCertification(request)).build();
}
I have then developed the following test using Mockito and SpringRunner.
#Test
public void givenValidToken_whenAddingCertification_thenCorrect() {
CertificationRequest certificationRequest = new CertificationRequest();
certificationRequest.setName("name");
Certification certification = new Certification();
when(certificationService.addCertification(certificationRequest)).thenReturn(certification);
given()
.contentType(ContentType.JSON)
.body(certificationRequest)
.when()
.post("/certifications")
.then()
.assertThat()
.statusCode(200)
.contentType(ContentType.JSON)
.log()
.all();
}
Written just like that, I receive the following error when it is executed.
HTTP/1.1 200
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Fri, 26 Jun 2020 18:33:35 GMT
java.lang.AssertionError: 1 expectation failed.
Expected content-type "JSON" doesn't match actual content-type "".
On the other hand, if I add null in place of certificationRequest and send an empty body in RestAssured , it works fine.
Why does it return an empty body when sent with a request body ?

At least one of your problems is the following:
when(certificationService.addCertification(certificationRequest)).thenReturn(certification);
You need a Matcher instead of certificationRequest. If you want to match any Request you can use ArgumentMatchers.any(). If you want to check for a specific Request you can use ArgumentMatchers.eq(certificationRequest). Note that ArgumentMatchers.eq(...) will only work if you've provided a valid equals method (Or if you pass exactly the same argument, afair).
So for example:
when(certificationService.addCertification(ArgumentMatchers.eq(certificationRequest))).thenReturn(certification);
If that doesn't solve your problem, I would try to print the response and check what you get there.

Related

Using Postman and Soapui I get a 400 when hitting a Spring Boot endpoint, but Swagger has no problem

The endpoint is in a RestController with this signature:
#PostMapping(value = "/unclaim")
#Operation(summary = "Unclaim Tasks ")
public BaseResponse<String> claimTasks(
#RequestParam(required = true, name = "taskIds") Long taskIds[]
)
{
If I use Soap ui to the correct URL ( I know I got that right, b/c if I append another character to it, I get a 404 ) I send this payload:
{
taskIds: [ 444, 34, 55 ]
}
Doing this in SoapUI and Postman both give 400s and no explanation :
HTTP/1.1 400
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Set-Cookie: JSESSIONID=C18701F799961FEECF967457574EB914; Path=/tlmapi; HttpOnly
Content-Length: 0
Date: Fri, 02 Sep 2022 16:11:44 GMT
Connection: close
But going to the swagger-ui.html page for this controller lets me construct a request that works :
So what's the difference ? Or is there a way to see the payload that swagger is sending?
Turns out that I accidentally was using the #RequestParam annotation on the list, instead of #RequestBody. Further, the param was Required, so spring rejected it and ignored my Json payload from SoapUI and Postman.
Hope this helps someone not waste a couple of hours...

How to stop Spring MVC from automatically adding the "Content-Length: 0" header to HEAD responses?

I'm specifically trying to test the case where my application doesn't receive a Content-Length header from the server, so I've set up my code not to include that header, but for some reason Spring is including it anyway with a value of 0:
#RequestMapping(value = "/test", method = RequestMethod.HEAD)
public void headTest(HttpServletRequest request, HttpServletResponse response) {
response.addDateHeader("Date", System.currentTimeMillis());
response.addHeader("Accept-Ranges", "bytes");
response.addHeader("Content-Type", "video/mp4");
}
$ curl -I http://myserver.com:8600/test
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Date: Thu, 28 Jul 2022 01:05:11 GMT
Accept-Ranges: bytes
Content-Type: video/mp4
Content-Length: 0
How can I stop Spring from including this header?
Setting a header to null to effectively remove it from the response works for embedded Tomcat and might work for other servers:
response.setHeader("Content-Length", null);

What defines jqXHR as "failed"

I have a ajax request to a spring security backend. What happens for some reason is that .then doesn't occur ever. What I found out is that .fail occurs on every request, even though the request goes through, the login on the backend works and it returns a response with status code 200. So what defines a jqXHR as failed and what do I need to add in the response so it works as it should?
Here is my ajax request:
// Creates request object
function makeRequest(method, module, endpoint) {
return req = {
method,
url: serverBaseUrl + module + '/' + endpoint
};
}
// Function to return POST promise
function post (module, endpoint, data) {
let req = makeRequest('POST', module, endpoint);
req.data = data;
return $.ajax(req);
}
And here is the response I get from my spring security setup:
HTTP/1.1 200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Wed, 28 Mar 2018 01:02:20 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: JSESSIONID=8D6265E912D5DFCF418238F18586AFE1; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
After all my problem was in my $.ajax request. I had a dataType parameter added as application/json. That seems to be not valid. Found it out when i printed the error from the request when it failed. Got the answer from here:
jquery ajax call return JSON parsing error

rest assured sprint security login

I am trying to test my app using rest assured, I am using spring security
This is sthe code
RestAssured.baseURI = "http://myapp-breakid.rhcloud.com/";
RestAssured.port = 80;
Response response = expect().given().auth().form("admin", "sababa1.",springSecurity().withLoggingEnabled(new LogConfig())).
when().get("login");
but this is the response:
HTTP/1.1 302 Found
Date: Mon, 01 Dec 2014 20:38:57 GMT
Server: Apache-Coyote/1.1
Location: http://myapp-breakid.rhcloud.com/index
Content-Length: 0
Set-Cookie: JSESSIONID=32E5F577A6885826DF17ACEE4B3386AF; Path=/; HttpOnly
Accept-Ranges: none
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/plain
What am I missing ?
You don't need to go to the login page to login, REST Assured does this automatically. This works:
RestAssured.baseURI = "http://myapp-breakid.rhcloud.com";
RestAssured.authentication = form("admin", "sababa1.", springSecurity());
get("/index").prettyPrint();
What happens here is that form authentication is automatically performed before each request. If it's important to use the same session in multiple requests you should use a session filter. For example:
RestAssured.baseURI = "http://myapp-breakid.rhcloud.com";
SessionFilter sessionFilter = new SessionFilter();
given().
auth().form("admin", "sababa1.", springSecurity()).
filter(sessionFilter).
when().
get("/index");
// Session filter will automatically capture the session id and you can reuse it in subsequent requests.
given().
filter(sessionFilter).
when().
get("/another_protected_resource").
then().
statusCode(200);
You can also get the sessionId from the SessionFilter and use it like this:
given().
sessionId(sessionFilter.getSessionId()).
when().
get("/another_protected_resource").
then().
statusCode(200);

Google OAuth 2: response_type error on token request

I am trying to return an OAuth 2 response code for an OAuth response token. However, my request returns the following error which has zero results in google. I tried changing response_type to "token" instead of "code" but that didn't work either.
OAuth 2 parameters can only have a single value: response_type
Request Details:
scope=https://www.googleapis.com/auth/userinfo.email
client_secret=_____
response_type=code
grant_type=authorization_code
redirect_uri=http://localhost/folder/
client_id=____.apps.googleusercontent.com
code=_____
I'm sending this second-step payload to POST https://accounts.google.com/o/oauth2/auth
What is wrong with my request?
Edit
I just realized that there is the https://accounts.google.com/o/oauth2/token URL that should be used for this request. However, changing to that URL now gives:
HTTP/1.0 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Date: Fri, 27 Jul 2012 22:44:35 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
{
"error" : "invalid_request"
}
Edit 2
Removing the response_type and changing the URL like above solved this.
After receiving the authorization code you have to ask '/o/oauth2/token' for the access token. This request takes no 'scope' and no 'response_type' parameters. See the Google documentation for more details.
After trying out a couple of methods, the required parameters to make the OAUTH2 call are
redirect_uri, response_type, scope, client_id. I kept on debugging the oauth call based on the error report I received.

Resources