java.lang.AssertionError when executing unit test - java

I got a java.lang.AssertionError when I was attempting to verify the href. The response body looks fine,
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"itemName":"ThinkPad","links":[{"rel":"self","href":"http://localhost/items/001"}]}
Forwarded URL = null
Redirected URL = null
Cookies = []
but when called this sentence: andExpect(jsonPath("$.links[0].href", hasItem(endsWith("/items/001"))))
The error occured:
java.lang.AssertionError: JSON path "$.links[0].href"
Expected: a collection containing ""
but: was "http://localhost/items/001"
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:74)
at org.springframework.test.web.servlet.result.JsonPathResultMatchers$1.match(JsonPathResultMatchers.java:86)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
at scnz.api.controller.ItemDispatchControllerTest.getCurrentStock(ItemDispatchControllerTest.java:62)
Here is the test code:
#Test
public void getCurrentStock() throws Exception {
Item item = new Item("001", "ThinkPad");
when(service.retrieve("001")).thenReturn(item);
mockMvc.perform(get("/items/001"))
.andDo(print())
.andExpect(jsonPath("$.itemName", is(item.getItemName())))
.andExpect(jsonPath("$.links[0].href", hasItem(endsWith("/items/001"))))
.andExpect(status().isOk());
Can anyone figure out where is wrong?

The actual result of jsonPath(...) for "$.links[0].href" is just a String as stated in the AssertionError.
The expected result for hasItem(...) is a collection as stated in the AssertionError.
In your case therefore just use endsWith(...) withouch hasItem(...). If your expression for jsonPath(...) returns a collection (e.g. via "$.links[*].href") instead of a single item you should use hasItem(...).

Related

MockServer | Return simple list in HttpResponse

We're calling an external API that return a simple List, not DTO/Json, like ResponseEntity<List<String>>
In my tests I'm trying to mock the response using mockServer but failed to return the result as List (just String as it not helped me):
mockServer.when(restTemplate.getForObject(any(), any()))
.respond(HttpResponse.response("{\"40\", \"50\"}")
.withStatusCode(200)
.withDelay(TimeUnit.SECONDS, 1));
String user = "user";
String password = "password";
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(user, password));
List<String> retList = restTemplate.getForObject(URI, List.class);
I tried with [, ], {, }, none of them, double parenthesis but failed to return the response as List..
Will be glad to know to do that correctly, thanks!
P.s. in the code all works well with the real API, response came as list as well. The issue is only in the tests, the error is:
"Could not extract response: no suitable HttpMessageConverter found
for response type [interface java.util.List] and content type
[application/octet-stream]"

How to get javax.validation errors messages and check this messages on HTTP 400 error test?

I'm using the javax.validation in my objects and in my annotation I have the errors messages like this:
#NotNull(message = "This name can't be a null parameter")
private String name;
When I use the #Valid on my endpoint the java will check my validations and return a error 400 with a list of errors inside. And in my integration test I check the error like this:
#Test
public void saveUser() throws Exception{
User user = builder.newUser();
getMockMvc().perform(post(URL_USER)
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(user)))
.andExpect(status().isBadRequest());
}
But this test are incomplete, because I dont check the error message.I need a way to check my message "This name can't be a null parameter". I know... This message come in a array of errors in a parameter called defaultMessage I think. Someone can help me?
You can assign the returning message with andReturn() to MvcResult then you can get response as String. After, you can parse (I used org.json here) this returning string and get error message.
final MvcResult mvcResult = getMockMvc().perform(post(URL_USER)
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(user)))
.andExpect(status().isBadRequest())
.andReturn();
final String resultString = mvcResult.getResponse().getContentAsString();
final JSONObject jsonObject = new JSONObject(resultString);
System.out.println(jsonObject.get("message"))

Getting bad response using JRAW

I am trying to read data from reddit using java. I am using JRAW.
Here is my code:
public class Main {
public static void main(String args[]) {
System.out.println('a');
String username = "dummyName";
UserAgent userAgent = new UserAgent("crawl", "com.example.crawl", "v0.1", username);
Credentials credentials = Credentials.script(username, <password>,<clientID>, <client-secret>);
NetworkAdapter adapter = new OkHttpNetworkAdapter(userAgent);
RedditClient reddit = OAuthHelper.automatic(adapter, credentials);
Account me = reddit.me().about();
System.out.println(me.getName());
SubmissionReference submission = reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/shady_insurance_work_around_to_pay_for_my_dexcom/");
RootCommentNode rcn = submission.comments();
System.out.println(rcn.getDepth());
System.out.println();
// Submission submission1 = submission.inspect();
// System.out.println(submission1.getSelfText());
// System.out.println(submission1.getUrl());
// System.out.println(submission1.getTitle());
// System.out.println(submission1.getAuthor());
// System.out.println(submission1.getCreated());
System.out.println("-----------------------------------------------------------------");
}
}
I am making two requests as of now, first one is reddit.me().about(); and the second is reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/ shady_insurance_work_around_to_pay_for_my_dexcom/");
The output is:
a
[1 ->] GET https://oauth.reddit.com/api/v1/me?raw_json=1
[<- 1] 200 application/json: '{"is_employee": false, "seen_layout_switch": true, "has_visited_new_profile": false, "pref_no_profanity": true, "has_external_account": false, "pref_geopopular": "GL(...)
dummyName
[2 ->] GET https://oauth.reddit.com/comments/https%3A%2F%2Fwww.reddit.com%2Fr%2Fdiabetes%2Fcomments%2F9rlkdm%2Fshady_insurance_work_around_to_pay_for_my_dexcom%2F?sort=confidence&sr_detail=false&(...)
[<- 2] 400 application/json: '{"message": "Bad Request", "error": 400}'
Exception in thread "main" net.dean.jraw.ApiException: API returned error: 400 (Bad Request), relevant parameters: []
at net.dean.jraw.models.internal.ObjectBasedApiExceptionStub.create(ObjectBasedApiExceptionStub.java:57)
at net.dean.jraw.models.internal.ObjectBasedApiExceptionStub.create(ObjectBasedApiExceptionStub.java:33)
at net.dean.jraw.RedditClient.request(RedditClient.kt:186)
at net.dean.jraw.RedditClient.request(RedditClient.kt:219)
at net.dean.jraw.RedditClient.request(RedditClient.kt:255)
at net.dean.jraw.references.SubmissionReference.comments(SubmissionReference.kt:50)
at net.dean.jraw.references.SubmissionReference.comments(SubmissionReference.kt:28)
at Main.main(Main.java:36)
Caused by: net.dean.jraw.http.NetworkException: HTTP request created unsuccessful response: GET https://oauth.reddit.com/comments/https%3A%2F%2Fwww.reddit.com%2Fr%2Fdiabetes%2Fcomments%2F9rlkdm%2Fshady_insurance_work_around_to_pay_for_my_dexcom%2F?sort=confidence&sr_detail=false&raw_json=1 -> 400
... 6 more
As it can been that my first request gives me a response of my username but in the second response i am getting a bad request 400 error.
To check whether my client ID and client secret were working correctly I did the same request using python PRAW library.
import praw
from praw.models import MoreComments
reddit = praw.Reddit(client_id=<same-as-in-java>, client_secret=<same-as-in-java>,
password=<same-as-in-java>, user_agent='crawl',
username="dummyName")
submission = reddit.submission(
url='https://www.reddit.com/r/redditdev/comments/1x70wl/how_to_get_all_replies_to_a_comment/')
print(submission.selftext)
print(submission.url)
print(submission.title)
print(submission.author)
print(submission.created_utc)
print('-----------------------------------------------------------------')
This gives the desired result without any errors so the client secret details must be working.
The only doubt I have is in the user agent creation in java UserAgent userAgent = new UserAgent("crawl", "com.example.crawl", "v0.1", username);.
I followed the following link.
What exactly does the target platform, the unique ID or the version mean. I tried to keep the same format as in the link. Also using the same username as in other places. On the other hand the user_agent in python was a string crawl.
Please tell me if I am missing anything and what could be the issue.
Thank you
P.S. I want to do this in java. not python.
Since your first query is working the credentials are correct. In JRAW don't give the whole URL but only the id in the submission function.
Change this
SubmissionReference submission = reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/shady_insurance_work_around_to_pay_for_my_dexcom/");
to this
SubmissionReference submission = reddit.submission("9rlkdm");
where the id is the random string after /comment/ in the URL.
Hope this helps.

Print response body when statusCode assert fails with restassured

I'm using Hamcrest to unit test a REST API.
When I send a request, I often check for a 200 status code like this :
public void myTest() {
url = "route/to/my/rest/api/";
secured().when().get(url).then().statusCode(200);
}
But when I get a wrong code status, I only get an assertion error. Is there a way to automatically dump the response body (which contains the error) when the status code doesn't match ?
The secured() method :
public RequestSpecification secured() {
return given().header("Authorization", "Bearer " + getAuth());
}
As I mentioned in the comments I used the following
secured().when().post(url).then().log().ifValidationFails(LogDetail.BODY).statusCode(200);
You can find the source in the documentation
You can add a message to the assertion when test fails:
.statusCode(describedAs("The test fails because ...", is(200)))

How to extract parameters from an object to show in parameters in documentation

I have the following API endpoint:
#ApiResponses(
value = {
#ApiResponse(code = 200, message = "OK",
responseHeaders = {
#ResponseHeader(name = "X-RateLimit-Limit", description = "The defined maximum number of requests available to the consumer for this API.", response = Integer.class),
#ResponseHeader(name = "X-RateLimit-Remaining", description = "The number of calls remaining before the limit is enforced and requests are bounced.", response = Integer.class),
#ResponseHeader(name = "X-RateLimit-Reset", description = "The time, in seconds, until the limit expires and another request will be allowed in. This header will only be present if the limit is being enforced.", response = Integer.class)
}
)
}
)
#ApiOperation(httpMethod = "GET", hidden = false, nickname = "Get Network Availability in JSON", value = "Get network availability for a product", response = AvailableToPromise.class, position = 1)
#RequestMapping(value = "/{product_id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> networkAvailabilityJsonResponse(
#RequestHeader HttpHeaders headers,
#PathVariable("product_id") String productId,
#Valid NetworkAvailabilityCmd cmd, //query params
BindingResult result)
throws Exception {}
}
Certain parameters, such as key are taken from the query and mapped into this object through Spring MVC.
However, in the parameters section of my endpoint in the swagger-ui, it's showing me a few odd things:
None of the variables that are in NetworkAvailabilityCmd show in this parameters list, and cmd itself shows as being located in the request body (it's actually located in the query). Is there a way to hide cmd and extract the params inside this object to show on the params list? I'd like the params list to look like this (with more params):
I'm able to do this if I use #ApiImplicitParams on the method endpoint, and write out each of the params. However, this NetworkAvailabilityCmd is used for many endpoints, and having the list of params on each endpoint is very messy. Being able to extract the variables from in the object would be far cleaner, and would prevent people from forgetting to add the entire list to new endpoints.
I imagine that it requires an annotation on NetworkAvailabilityCmd cmd, and potentially something on the variables in that class, but I can't seem to find what I'm looking for in the docs.
Thanks!
I found out that adding #ModelAttribute worked magically. This annotation is from Spring.

Categories

Resources