Unit Testing Download CSV in Spring - java

I am writing a unit test for an endpoint in Spring which sends a csv file as the response. I am able to do checks like checking Status of the respone and the content type, but how can I compare the contents of the CSV? I tried to convert the response to string and do the comparison but without any success. Can any one point me in the right direction?
Here is what I tried:
public void testDownloadCSV() throws Exception {
RequestBuilder request = MockMvcRequestBuilders.get
(getRequestMapping("/downloadCSV/" + ID))
.contentType(contentType);
ResultActions result = getMockMvc().perform(request);
String csvString = "CSV Data goes here";
String resultString=content().toString();
if (log.isDebugEnabled()) {
result.andDo(print());
Assert.assertTrue(csvString.equals(resultString));
}
// tests:
result.andExpect(status().isOk()).andExpect(content().contentType
(contentType));
}

Not sure what kind of differences are you seeing when your are comparing String contents. Common problem is lack/presence of whitespace characters.
If that's your case, Just use Java library called Hamcrest to compare your strings this way:
assertThat(actualContent, equalToIgnoringWhiteSpace(expectedContent));
If your logic is not order sensitive, I am afraid you'll need parse the CSV strings first into Lists, sort them and compare them afterwards.

Related

Rest API call encoding in Flutter and decoding in Java

My Flutter app calls a REST API method /user/search/<search string> and I am forming the URL endpoint using encodeQueryComponent like this:
String endpoint = "/user/search/"+Uri.encodeQueryComponent(searchString);
The back-end implemented in Java tries to retrieve the search string like this:
String value = URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
However, when the search string contains the + sign, the raw encode string in the back-end contains %2B and the decoded String contains space. As a temporary hack, I am currently doing value = value.replace("%2B", "+"); instead of decode. But this is obviously not the right approach because the search string may contain characters from any language or special characters.
Can someone tell me what is the right way to get the original string sent by the user in Java?

Converting JSON file to string in RestAssured (Java)

I'm using IntelliJ to learn RestAssured; this is completely new territory for me. I have a simple .json file in place and I want to have a API Response to assert if it's the same as the mentioned .json file.
Basically: If the output of the call equals what I have in the json file, it's all good.
I used the demo restapi.demoqa.com for quick reference. This is what I have right now:
#Test
public void ComparewithJSONinResources()
{
String CityResponse = ?????
RestAssured.baseURI = "http://restapi.demoqa.com/utilities/weather/city";
RequestSpecification httpRequest = RestAssured.given();
Response response = httpRequest.request(Method.GET, "/Hyderabad");
String responseBody = response.getBody().asString();
System.out.println(responseBody);
Assert.assertTrue(responseBody.equals(CityResponse));
response.body();
}
I have the .json file in place called CityResponse.json. For easy reference, say on the location c:/CityResponse.
Is it possible to convert the Json file to a string to assert that the API and the JSON are equal?
Comparing JSON as String will never give accurate results, as you will possibly see inconsistency in space, tabs (indentation), property (key-value pair) sequencing etc. Your best bet is to parse JSON into POJO using one of the many popular libraries (Ex. Jackson, GSON etc). And this deserialization you need for both RestAssured Http response & one you are reading from .json file, and once you have two java objects, use standard Java comparision by overriding equals method.

I want to write a java code, parse the last number from the URL.Then I need to check if that number is present in a excel. else If present return

I want to write a java code, that will basically parse the last number from the URL. Then I need to check, if that number is present in a excel. If not found show an error, else If present return me the row name.
Say URL: http://foxsd5174:3887/PD/outage/area/v1/device/40122480
and from the below excel I need to know, "40122480" falls under which category city or county?
City County Event Level
Device ID 40122480 277136436 268698851
to fetch value from URL i was thing of using the below code.
Please help me out.
Use this post in case you don't know how to get the last number of the url:
How to obtain the last path segment of an uri
To read the excel file use this tutorial https://www.callicoder.com/java-read-excel-file-apache-poi/ which uses apache poi library to get the job done.
Just compare the cell value with the last number of the url.
I wrote the below code to get the last digit of the URL.
public class smartoutage {
public static void main(final String[] args){
System.out.println(getLastBitFromUrl(
"http://goxsd5174:3807/PD/outage/areaEtr/v1/device/40122480?param=true"));
}
public static String getLastBitFromUrl(final String url){
return url.replaceFirst(".*/([^/?]+).*", "$1");
}
}
Output is 40122480
now i need to find if 40122480 is present in the excel and return me the row name for which it belong
City County Event Level
Device ID 40122480 277136436 268698851
Depending on the number of digits at the end of the URL you could parse it in multiple different ways. You could use regex, or substrings. To compare it to an excel file you could first convert the excel file into a csv (They are compatible) use BufferedReader along with FileReader to read in the file. Make an array of strings and using regex or any parsing method separate out the commas within the csv file you created. Then simply run a while loop that loops to EOF and check for the string you've parsed being "40122480" using the equals() method on type string and seeing if your string matches any of the strings you've just parsed from the file.
EDITED*
Rough and quick code I did in a few minutes to maybe help the parsing thing for you.
String parsedUrl[] = new String[8];
String url = "http://foxsd5174:3887/PD/outage/area/v1/device/40122480";
System.out.println(url);
parsedUrl = url.split("/");
System.out.println(parsedUrl[8]);

Remove indentation of xml files

I am writing a function that I will use for my unit tests. I want to compare XML files, but as one of them will be created by a Third party library I want to mitigate any possible differences because of different indentation. Thus I wrote the following function:
private String normalizeXML(String xmlString) {
String res = xmlString.replaceAll("[ \t]+", " ");
// leading whitespaces are inconsistent in the resulting xmls.
res = res.replaceAll("^\\s+", "");
return res.trim();
}
However this function is not removing the leading interval on each line of the XML.
When I write the function in this way (difference in the first regex):
private String normalizeXMLs(String xmlString) {
String res = xmlString.replaceAll("\\s+", " ");
// leading whitespaces are inconsistent in the resulting xmls.
res = res.replaceAll("^\\s+", "");
return res.trim();
}
It does remove the trailing white space, but it also makes the xml appear as a single line which is very troubling when you need to compare the differences.
I just can not justify why the first implementation does not displace the leading interval. Any ideas?
EDIT: Even more interesting is that if I make a single line manipulation:
String res = xmlString.replaceAll("^\\s+", "");
This line does not remove any of identation!
Rather than trying to manipulate the string representations, it would be safer to use a dedicated XML comparison tool such as XMLUnit that allows you to define exactly which differences are significant and which aren't. Trying to modify XML data using regular expressions is rarely a good idea, you should use a proper XML parser that knows all the rules of what makes well formed XML.
Maybe:
String res = xmlString.replaceAll("[ \\t]+", " ");
Not \t...
this one worked for me:
private static String normalizeXMLs(String xmlString) {
String res = xmlString.replaceAll("\\t", "");
return res.trim();
}
Good luck :)

Easiest way to compare two Excel files in Java?

I'm writing a JUnit test for some code that produces an Excel file (which is binary). I have another Excel file that contains my expected output. What's the easiest way to compare the actual file to the expected file?
Sure I could write the code myself, but I was wondering if there's an existing method in a trusted third-party library (e.g. Spring or Apache Commons) that already does this.
You might consider using my project simple-excel which provides a bunch of Hamcrest Matchers to do the job.
When you do something like the following,
assertThat(actual, WorkbookMatcher.sameWorkbook(expected));
You'd see, for example,
java.lang.AssertionError:
Expected: entire workbook to be equal
but: cell at "C14" contained <"bananas"> expected <nothing>,
cell at "C15" contained <"1,850,000 EUR"> expected <"1,850,000.00 EUR">,
cell at "D16" contained <nothing> expected <"Tue Sep 04 06:30:00">
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
That way, you can run it from your automatted tests and get meaningful feedback whilst you're developing.
You can read more about it at this article on my site
Here's what I ended up doing (with the heavy lifting being done by DBUnit):
/**
* Compares the data in the two Excel files represented by the given input
* streams, closing them on completion
*
* #param expected can't be <code>null</code>
* #param actual can't be <code>null</code>
* #throws Exception
*/
private void compareExcelFiles(InputStream expected, InputStream actual)
throws Exception
{
try {
Assertion.assertEquals(new XlsDataSet(expected), new XlsDataSet(actual));
}
finally {
IOUtils.closeQuietly(expected);
IOUtils.closeQuietly(actual);
}
}
This compares the data in the two files, with no risk of false negatives from any irrelevant metadata that might be different. Hope this helps someone.
A simple file comparison can easily be done using some checksumming (like MD5) or just reading both files.
However, as Excel files contain loads of metadata, the files will probably never be identical byte-for-byte, as James Burgess pointed out.
So you'll need another kind of comparison for your test.
I'd recommend somehow generating a "canonical" form from the Excel file, i.e. reading the generated Excel file and converting it to a simpler format (CSV or something similar), which will only retain the information you want to check. Then you can use the "canonical form" to compare with your expected result (also in canonical form, of course).
Apache POI might be useful for reading the file.
BTW: Reading a whole file to check its correctnes would generally not be considere a Unit test. That's an integration test...
I needed to do something similar and was already using the Apache POI library in my project to create Excel files. So I opted to use the included ExcelExtractor interface to export both workbooks as a string of text and asserted that the strings were equal. There are implementations for both HSSF for .xls as well as XSSF for .xlsx.
Dump to string:
XSSFWorkbook xssfWorkbookA = ...;
String workbookA = new XSSFExcelExtractor(xssfWorkbookA).getText();
ExcelExtractor has some options for what all should be included in the string dump. I found it to have useful defaults of including sheet names. In addition it includes the text contents of the cells.
The easiest way I find is to use Tika.
I use it like this:
private void compareXlsx(File expected, File result) throws IOException, TikaException {
Tika tika = new Tika();
String expectedText = tika.parseToString(expected);
String resultText = tika.parseToString(result);
assertEquals(expectedText, resultText);
}
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.13</version>
<scope>test</scope>
</dependency>
You could use javaxdelta to check whether the two files are the same. It's available from here:
http://javaxdelta.sourceforge.net/
Just found out there's something in commons-io's FileUtils. Thanks for the other answers.
Please, take a look at the site to compare the binary files, http://www.velocityreviews.com/forums/t123770-re-java-code-for-determining-binary-file-equality.html
Tiger
You may use Beyond Compare 3 which can be started from command-line and supports different ways to compare Excel files, including:
Comparing Excel sheets as database tables
Checking all textual content
Checking textual content with some formating
To test only content of the first sheets in Kotlin (easily can be converted to java).
private fun checkEqualityExcelDocs(doc : XSSFWorkbook, doc1 : XSSFWorkbook) : Boolean{
val mapOfCellDoc = doc.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
val mapOfCellDoc1 = doc1.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
if(mapOfCellDoc.size == mapOfCellDoc1.size){
return mapOfCellDoc.entries.all { mapOfCellDoc1.containsKey(it.key) && mapOfCellDoc[it.key] == mapOfCellDoc1[it.key]}
}
return false
}
data class IndexInThePivotTable(val row: Int, val col: Int)
and in your code add assert
assertTrue(checkEqualityExcelDocs(expected, actual), "Docs aren't equal!")
as you can see doc.toList().first() will take only the first sheet of document, if you need to compare each sheet respectively change code a little.
Also it is quite good idea to not take into account "" empty strings cells, I didn't need this functionality (As well, simply add this part, if you need).
also it can be useful information
//first doc I've got from outputstream such way
val out = ByteArrayOutputStream()
//some method which writes excel to outputstream
val firstDoc = XSSFWorkbook(ByteArrayInputStream(out.toByteArray()))
and second doc from file to compare with
val secondDoc = XSSFWorkbook(Test::class.java.getClassLoader().getResource("yourfile.xlsx").path)
Maybe... compare MD5 digests of each file? I'm sure there are a lot of ways to do it. You could just open both files and compare each byte.
EDIT: James stated how the XLS format might have differences in the metadata. Perhaps you should use the same interface you used to generate the xls files to open them and compare the values from cell to cell?

Categories

Resources