How do I handle this error for Hamcrest matcher - java

I am getting the following error using Hamcrest Matcher library.
"The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (List, AnyOf)"
What I am trying is
Sample code
List<String> poster_path_image2;
assertThat(poster_path_image2, anyOf(startsWith("https:"), startsWith("null")));
I need to check if a url is valid and null value is acceptable as well.
I am new to this library and stumped by this error.

It looks like poster_path_image2 is of type List. but the Matcher startsWith can just work on String. Check the types of your variables and what the matcher is able to process.
Maybe you want to get the first element of your List or repeat the assertion for every item in the list.
String path = "your test String";
assertThat(path, anyOf(startsWith("https:"), is(nullValue())));
I changed the second matcher as I think you want the check if your String is null and not if it contains the String value "null".

Related

Matching Boolean true value using jsonPath

I am trying to write a JUnit test, which checks the value of received JSON. I access these values in the JSON using jsonPath. I want to check if a value is true. For simple jsonPaths, it works for me, but when I write more complex jsonPath query, it does not and I am getting this Assertion Error:
Expected: is <true>
but: was <[true]>
My JSON:
{...
,"trips":
[
{...
,"employee":{"name":"Ordinary Joe","login":"joe","contractor":true}
,...
},
...
],
...
}
Problematic assertion
.andExpect(jsonPath("$.trips[?(#.employee.login=='joe')].employee.contractor", is(true)));
What I've tried
I tried to match the value also with new Boolean(true), boolean[] array with one true value and after examination of is() matcher also with String.valueOf(true) however it also did not match.
My question
How should I correctly match this true value? What exactly these [] braces mean in the test output?
In the further investigation, I actually found that jsonPath somehow converts the obtained true value to a JsonArray with one item and therefore it is not possible to match it with is(true) matcher. I am not sure why JsonPath does so.
I found the following working workaround using hasItem matcher instead:
.andExpect(jsonPath("$.trips[?(#.employee.login=='joe')].employee.contractor", hasItem(true)))
.andExpect(jsonPath("$.trips[?(#.employee.login=='joe')].employee.contractor", not(hasItem(false))))

Java Regex - Pattern.match fails to deal with lazy match

This is the sample code
String m_testPattern = "AB.*?";
String m_testMatcherString = "ABCDCDCDCD";
final Pattern pattern = Pattern.compile(m_testPattern);
final Matcher matcher = pattern.matcher(m_testMatcherString);
if (matcher.matches()) {
// This means the regex matches
System.out.println("Successful comparison");
} else {
// match failed
System.out.println("Comparison failed !!!");
}
Ideally the match operation should result in a failure and give me output as "Comparison failed !!!"
But this code snippet gives me "Successful comparison" as output
I checked online regex tools with the same input and the result was different
I did the trial in this site http://regexr.com/v1/
Here when I put AB.*? in the regex and ABCDCDCDCD as the string to be compared, then the search stops at AB.
This means the comparison performed is a Lazy Comparison and not a greedy one
Can anyone please explain why the same use case fails in case of Java Pattern.match function ?
My test case is something like
1. regex AB\wCD should match with ABZCD plus fail at AB2CD
2. AB\w{2}CD would match ABZZCD
3. AB\d{1,3}CD should match AB555CD or AB6CD or AB77CD plus fail at ABCD or AB9999CD etc
4. AB.* should match AB(followed by anything)
5. AB.*? should fail if input like ABCDCDCD is given for comparison
All the 4 steps is passed successfully while using matcher.matches() function <br/>
Only the fifth one gives a wrong answer. (5th scenario also gives a success message eventhough it should fail)
Thanks in advance
matches()
return true if the whole string matches the given pattern.
find()
tries to find a substring that matches the pattern.

Java Regex with Pattern and Matcher

I am using Pattern and Matcher classes from Java ,
I am reading a Template text and I want to replace :
src="scripts/test.js" with src="scripts/test.js?Id=${Id}"
src="Servlet?Template=scripts/test.js" with src="Servlet?Id=${Id}&Template=scripts/test.js"
I'm using the below code to execute case 2. :
//strTemplateText is the Template's text
Pattern p2 = Pattern.compile("(?i)(src\\s*=\\s*[\"'])(.*?\\?)");
Matcher m2 = p2.matcher(strTemplateText);
strTemplateText = m2.replaceAll("$1$2Id=" + CurrentESSession.getAttributeString("Id", "") + "&");
The above code works correctly for case 2. but how can I create a regex to combine both cases 1. and 2. ?
Thank you
You don't need a regular expression. If you change case 2 to
replace Servlet?Template=scripts/test.js with Servlet?Template=scripts/test.js&Id=${Id}
all you need to do is to check whether the source string does contain a ? if not add ?Id=${Id} else add &Id=${Id}.
After all
if (strTemplateText.contains("?") {
strTemplateText += "&Id=${Id}";
}
else {
strTemplateText += "?Id=${Id}";
}
does the job.
Or even shorter
strTemplate += strTemplateText.contains("?") ? "&Id=${Id}" : "?Id=${Id}";
Your actual question doesn't match up so well with your example code. The example code seems to handle a more general case, and it substitutes an actual session Id value instead of a reference to one. The code below takes the example code to be more indicative of what you really want, but the same approach could be adapted to what you asked in the question text (using a simpler regex, even).
With that said, I don't see any way to do this with a single replaceAll() because the replacement text for the two cases is too different. You could nevertheless do it with one regex, in one pass, if you used a different approach:
Pattern p2 = Pattern.compile("(src\\s*=\\s*)(['\"])([^?]*?)(\\?.*?)?\\2",
Pattern.CASE_INSENSITIVE);
Matcher m2 = p2.matcher(strTemplateText);
StringBuffer revisedText = new StringBuffer();
while (m2.find()) {
// Append the whole match except the closing quote
m2.appendReplacement(revisedText, "$1$2$3$4");
// group 4 is the optional query string; null if none was matched
revisedText.append((m2.group(4) == null) ? '?' : '&');
revisedText.append("Id=");
revisedText.append(CurrentESSession.getAttributeString("Id", ""));
// append a copy of the opening quote
revisedText.append(m2.group(2));
}
m2.appendTail(revisedText);
strTemplateText = revisedText.toString();
That relies on BetaRide's observation that query parameter order is not significant, although the same general approach could accommodate a requirement to make Id the first query parameter, as in the question. It also matches the end of the src attribute in the pattern to the correct closing delimiter, which your pattern does not address (though it needs to do to avoid matching text that spans more than one src attribute).
Do note that nothing in the above prevents a duplicate query parameter 'Id' being added; this is consistent with the regex presented in the question. If you want to avoid that with the above approach then in the loop you need to parse the query string (when there is one) to determine whether an 'Id' parameter is already present.
You can do the following:
//strTemplateText is the Template's text
String strTemplateText = "src=\"scripts/test.js\"";
strTemplateText = "src=\"Servlet?Template=scripts/test.js\"";
java.util.regex.Pattern p2 = java.util.regex.Pattern.compile("(src\\s*=\\s*[\"'])(.*?)((?:[\\w\\s\\d.\\-\\#]+\\/?)+)(?:[?]?)(.*?\\=.*)*(['\"])");
java.util.regex.Matcher m2 = p2.matcher(strTemplateText);
System.out.println(m2.matches());
strTemplateText = m2.replaceAll("$1$2$3?Id=" + CurrentESSession.getAttributeString("Id", "") + (m2.group(4)==null? "":"&") + "$4$5");
System.out.println(strTemplateText);
It works on both cases.
If you are using java > 1.6; then, you could use custom-named group-capturing features for making the regex exp. more human-readable and easier to debug.

java regex matcher results != to notepad++ regex find result

I am trying to extract data out of a website access log as part of a java program. Every entry in the log has a url. I have successfully extracted the url out of each record.
Within the url, there is a parameter that I want to capture so that I can use it to query a database. Unfortunately, it doesn't seem that the web developers used any one standard to write the parameter's name.
The parameter is usually called "course_id", but I have also seen "courseId", "course%3DId", "course%253Did", etc. The format for the parameter name and value is usually course_id=_22222_1, where the number I want is between the "_" and "_1". (The value is always the same, even if the parameter name varies.)
So, my idea was to use the regex /^.*course_id[^_]*_(\d*)_1.*$/i to find and extract the number.
In java, my code is
java.util.regex.Pattern courseIDPattern = java.util.regex.Pattern.compile(".*course[^i]*id[^_]*_(\\d*)_1.*", java.util.regex.Pattern.CASE_INSENSITIVE);
java.util.regex.Matcher courseIDMatcher = courseIDPattern.matcher(_url);
_courseID = "";
if(courseIDMatcher.matches())
{
_courseID = retrieveCourseID(courseIDMatcher.group(1));
return;
}
This works for a lot of the records. However, some records do not record the course_id, even though the parameter is in the url. One such example is the record:
/webapps/contentDetail?course_id=_223629_1&content_id=_3641164_1&rich_content_level=RICH&language=en_US&v=1&ver=4.1.2
However, I used notepad++ to do a regex replace on this (in fact, every) url using the regex above, and the url was successfully replaced by the course ID, implying that the regex is not incorrect.
Am I doing something wrong in the java code, or is the java matcher broken?

Why my regular expression matches but does not capture a group?

I am trying to extract the information from the following string:
//YES: We got a match.
I want to extract the information defining two groups
Everything between // and :
all the rest behind :
The pattern matches correctly but I cannot extract the groups.
String example = "//YES: We got a match.";
String COMMENT_PATTERN = "//(\\w+):(.*)";
Pattern pattern = Pattern.compile(COMMENT_PATTERN);
example.matches(COMMENT_PATTERN); // true
Matcher matcher = pattern.matcher(example);
matcher.group(1); // raises an exception
I tried it as well with named groups:
String COMMENT_PATTERN = "//(?<init>\\w+):(?<rest>.*)";
...
matcher.group("init"); // raises an exception
Why my patterns cannot extract the specified groups?
You have to call either find() or matches() on the matcher to cause it to run the matching process before you can extract groups. The
example.matches(COMMENT_PATTERN);
creates its own internal Matcher, calls matches() and then discards the Matcher - it's equivalent to
Pattern.compile(COMMENT_PATTERN).matcher(example).matches()

Categories

Resources