would like to seek for help on my JUnit testing. On my method, I was able to cover all except the part where IOException needs to be thrown. I have done many workaround on this, but none of it seemed to work.
Here is the method where IOException was not covered on unit test
public String GetstrXMLValue(String strXML, String strCriteria) {
SAXBuilder builder = new SAXBuilder();
builder.setProperty(XMLConstants.ACCESS_S1, "");
builder.setProperty(XMLConstants.ACCESS_S2, "");
Document xmlDocument;
String strValue = "";
ErrorHandler objErrHdl = new ErrorHandler();
try {
InputStream objStream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
xmlDocument = builder.build(objStream);
XPathFactory xpath = XPathFactory.instance();
XPathExpression<Object> expr = xpath.compile(strCriteria);
List<Object> xPathSearchedNodes = expr.evaluate(xmlDocument);
if (xPathSearchedNodes.size() > 0) {
Content content = (Content) xPathSearchedNodes.get(0);
strValue = content.getValue().toString();
}
} catch (JDOMException e) {
objErrHdl.LogError(this.getClass().getName(), "GetstrXMLValue", "ERROR RETRIEVING XML VALUES (XML=" + strXML + ";CRITERIA=" + strCriteria + ")", e.toString());
} catch (IOException e) {
objErrHdl.LogError(this.getClass().getName(), "GetstrXMLValue", "ERROR RETRIEVING XML VALUES (XML=" + strXML + ";CRITERIA=" + strCriteria + ")", e.toString());
} catch (Exception e) {
objErrHdl.LogError(this.getClass().getName(), "GetstrXMLValue", "ERROR RETRIEVING XML VALUES (XML=" + strXML + ";CRITERIA=" + strCriteria + ")", e.toString());
}
return strValue;
}
Here is my JUnit testing
#Test
public void testGetstrXMLValueThrowsIOException() throws IOException, ParserConfigurationException, SAXException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
OutputStream responseBody = new ByteArrayOutputStream();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
" <RESULT>\r\n" +
" <SHORT_NAME>XXXXXXXXXXXXX</SHORT_NAME>\r\n" +
" <ID_CODE>9999999999999</ID_CODE>\r\n" +
" </RESULT>";
xmlHandler.XMLGenerateRootResult();
xmlHandler.GetstrXMLValue(xml, ".//RESULT/ID_CODE/text()");
try
{
InputStream input = XMLHandlerTest.readXML(xml);
byte[] buffer = new byte[1024];
int bytesRead;
input.close();
while ((bytesRead = input.read(buffer)) > 0)
{
responseBody.write(buffer, 0, bytesRead);
throw new IOException();
}
}
catch(IOException e)
{
System.out.println(e);
}
}
Your question is unclear.
You meant: How do I make the test fail if an IOException occurs
By not catching it. The default behaviour of a test case, if it throws an exception, is that the test case is considered failed. Note that System.out.println(e); is tossing out a humongous amount of useful info about the error, AND means the code will keep going. e.printStackTrace();, LOG.something() or System.out.println() are basically always bugs if you do that in a catch block. Stop doing that. If you can't be bothered to deal with the problem or don't know how, the only correct 'I dunno' code in a catch block is this:
catch (Whatever e) {
throw new RuntimeException("uncaught", e);
}
In this case, just remove the try/catch entirely, and your test will properly fail if an IOException occurs.
You meant: I need to test my method if IT throws an IOException; how do I test that it does the right thing?
Well, there's no point, is there? Your method is obviously broken if an IOException happens, because your method will log something and just keep on going. That's rather silly, and I don't think it's useful for me to try to explain to you how to write a unit test that tests that your method returns the arbitrary misleading value and writes a log message. I don't think anybody would actually want that behaviour.
Make your method throw something on error, and you can easily confirm that it does this with junit. Give it its own test method and annotate:
#Test(expected = IOException.class)
public void testSomething() {
if (Boolean.TRUE) throw new IOException();
// this test will _PASS_, because we said
// it SHOULD throw IOException.
}
You meant: How do I make this method throw IOException?
That's not easily possible unless you kind of ruin your method to make it possible. If you stop catching exceptions and turning them into silly things (a log message and continuing with the code), the code coverage ceases to be an issue. Just get rid of those catch blocks entirely.
Related
I have a method that throws my custom Exception.
My custom Exception:
public class IllegalEntryException extends Exception
{
public IllegalEntryException(String message)
{
super(message);
}
}
and my method:
public Order(String[] value) throws IllegalEntryException
{
String timeString = value[0];
try
{
this.time = Integer.parseInt(timeString);
}
catch(NumberFormatException e)
{
throw new IllegalEntryException("First entry of each column, time must be int, found at row ");
}
}
Now on the method which actually calls this function (which is also a constructor) I have access to a variable which tracks the row number of the file on which this error occurs. I want to add on this row number to the message when the exception was thrown (i.e. in the constructor) so that when I handle it finally over there the row number is also printed.
Something like:
try
{
calltoFunction(); // exception is thrown
// somehow add the row number to the message
}
catch {}//Handle the exception over here
How can I achieve this?
Really sorry I was looking for something like this:
try
{
Order order = new Order(values);
}
catch(IllegalEntryException e)
{
String error = e.getMessage() + "row_no";
System.err.println(error);
}
When an exception is thrown, you can access it's stacktrace (which also contains all method calls on the stack, including their class name and the line which caused the exception) by calling:
e.getStackTrace();
Furthermore,
e.printStackTrace();
will print said stacktrace to the System.out stream, which should suffice for debugging purposes.
I don't know what you are trying to achieve by having the row number in the catch block, but you could try getting the whole stacktrace as a string by the following means:
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter );
String stackTrace = stringWriter.toString();
From the string stackTrace, you could then figure out your row number.
My java code receives stream data like twitter. I need to store the data e.g. 10000 records for each file. So, I need to recreate the file writer and buffered writer to create a new file then write data on it.
// global variables
String stat;
long counter = 0;
boolean first = true;
Date date;
SimpleDateFormat format;
String currentTime;
String fileName;
BufferedWriter bw = null;
FileWriter fw = null;
public static void main(String[] args) {
String dirToSave = args[0];
String fileIdentifier = args[1];
createFile(dirToSave, fileIdentifier);
StatusListener listener = new StatusListener() {
#Override
public void onStatus(Status status) {
stat = TwitterObjectFactory.getRawJSON(status);
try {
if(bw!=null){
bw.write(stat + "\n");
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
counter++;
if (counter == 10000) {
createFile(dirToSave, fileIdentifier);
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
counter = 0;
}
}
};
TwitterStream twitterStream = new TwitterStreamFactory(confBuild.build()).getInstance();
twitterStream.addListener(listener);
// twitterStream.filter(filQuery);
}
public static void createFile(String path, String fileIdentifier) {
date = new Date();
format = new SimpleDateFormat("yyyyMMddHHmm");
currentTime = format.format(date);
fileName = path + "/" + fileIdentifier + currentTime + ".json";
// if there was buffer before, flush & close it first before creating new file
if (!first) {
try {
bw.flush();
bw.close();
fw.close();
} catch (IOException ex) {
Logger.getLogger(LocalFile_All_en.class
.getName()).log(Level.SEVERE, null, ex);
}
} else {
first = false;
}
// create a new file
try {
fw = new FileWriter(fileName);
bw = new BufferedWriter(fw);
} catch (IOException ex) {
Logger.getLogger(Stack.class
.getName()).log(Level.SEVERE, null, ex);
}
}
However, i always get error after some hours.
SEVERE: null
java.io.IOException: Stream closed
EDIT: The error message says that, these codes throw the error
if (counter == 10000) {
createFile(dirToSave, fileIdentifier);
...
and
bw.flush();
What is the problem of my code? or is there a better way to write stream data like this?
If this error comes every now and then and writing after this error is ok again i think it can happen that bw is closed and not yet reopened while onStatus() tries to write of flush it.
So bw can be be not null but closed. You need to synchronize the closing/opening somehow.
For example make this stuff in onStatus() like so that you do not just write directly to bw but with some callbacks that handle the close/reopen new file.
Update: assuming here that this twitterStream can call onStatus() without waiting previous call finished. The first call has just closed the stream and the second is right after that writing to. Rare, but will happen in a long period of time.
Update2: this applies also to the flush() part.
I added this also as a short comment already but people often tell to get rid of static and especially global statics in java argumenting that it will cause big problems later which are hard to resolve/debug. This might be good case of it.
Read also:
Why are static variables considered evil?
Volatile Vs Static in java
Latter has an example how to sychronize concurrent requests.
I have a method which uses proxies to retrieve information from a server. Sometimes due to a bad proxy I get SocketException, SSLException, SSLHandshakeException or ConnectException
I want the method to retry on the exceptions above, but on the IOException or no exception I want a string returned
Here is the method I constructed to test different scenarios
public String getTest(int i, int current, int total)
{
String text = "";
try
{
if (i == 1)
throw new IOException();
else if (i == 2)
throw new SSLException("SSLEx");
else if (i == 3)
throw new SocketException();
else
text = "EVERYTHING GOOD";
}
catch (SSLException | SocketException re)
{
if (current < total)
{
System.out.println("Recalling " + current);
getTest(1, ++current, total);
}
}
catch (IOException ioe)
{
text = "HTTP ERROR";
}
catch (Exception e)
{
e.printStackTrace();
}
return text;
}
I call my test method by
System.out.println(c.getTest(3, 0, 5));
Initially the program would catch a SocketException then retry by passing 1 so I can emulate a working proxy but a server response with IOException as i = 1 but the method never returns the text "HTTP ERROR"
What do I need to change in order for this to work as expected?
In order to return the string returned by your recursive function call, you must place return before the recursive function call like so...
return getTest(1, ++current, total);
Right now you are simply running the recursive function and discarding its return value. Your logic then returns your text string from the initial call (which in the case of an SSLException looks like an empty string).
You could also accomplish the same effect by assigning text from the recursive function...
text = getTest(1, ++current, total);
Both statements, considering the rest of your logic, are equivalent.
I just write a simple commandwrapper in java, this is construction function:
Process process;
Thread in;
Thread out;
public CommandWrapper(Process process) {
this.process = process;
final InputStream inputStream = process.getInputStream();
// final BufferedReader
//final BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
final byte[] buffer = new byte[1024];
out = new Thread() {
// String line;
int lineNumber = 0;
public void run() {
try {
while (true) {
int count = inputStream.read(buffer);
System.out.println(lineNumber + ":"
+ new String(buffer, 0, count - 1));
// line=r.readLine();
// System.out.println(lineNumber+":"+line);
lineNumber++;
}
} catch (Exception e) {
}
}
};
final BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
final OutputStream outputStream = process.getOutputStream();
in = new Thread() {
String line;
public void run() {
try {
//while (true) {
outputStream.write((reader.readLine() + "/n")
.getBytes());
outputStream.flush();
//}
} catch (Exception e) {
}
}
};
}
public void startIn() {
in.start();
}
This is when it invoke:
public static void main(String[] args) {
try {
CommandWrapper command = new CommandWrapper(Runtime.getRuntime()
.exec("wget www.google.com"));
//command.startIn();
command.startOut();
} catch (Exception e) {
e.printStackTrace();
}
}
It works OK when I run simple command like ls -l or other local commander, but when I want to run wget command it is print out nothing as output. I do know why.
From the code you've shown and your description of how you use it, the best guess is that an exception occurs, and you silently swallow it. This happens whenever you have an empty catch-block, like this:
catch (Exception e) {
}
You happen to have one in the run() method of your out thread.
Silently swallowing exceptions is extremely bad practice.
You should never ever ever do this! Depending on your application the appropriate solution varies, but since you're writing a console application you probably want to print the stack trace of the exception. In Java, this is done with e.printStackTrace():
catch (Exception e) {
e.printStackTrace();
}
Another option (which might not be appropriate in this specific case) is to rethrow the exception, possibly after wrapping it in another exception (for example one you've written specifically for your application):
catch (Exception e) {
throw e;
}
// or
catch (Exception e) {
throw new MyOwnException(e);
}
Doing either of these two (printing stack trace or rethrowing) will ensure that no exceptions go unnoticed.
However, no rule without exceptions ;)
There are cases when it is appropriate to have empty catch-clauses. If you know that some operation might throw an exception and you just want to proceed when it happens, an empty catch-clause is a good way to do it. However, the cases where this is appropriated are limited to (at least) the following conditions:
You must know the specific type of the exception. You never want to catch a general exception (i.e. catch (Exception e) since that might be thrown for any reason which you cannot possibly predict. If you use empty catch clauses, always catch specific exception type (such as IOException).
You must know why the exception was thrown. You should only swallow exceptions that you know the origin of. If you swallow any other exceptions, you'll end up like in this situation, where your code doesn't do what you expect and you can't understand why. Swallowed exceptions are extremely difficult to debug, since they are, well, swallowed, and thereby hidden.
You must know that you don't care about the exception. The reason to use empty catch-clauses is mainly (read: only) to handle situations where the code you're using treats something as exceptional, while you do not. By exeptional in this context we mean "something that shouldn't really happen, and if it does, something is seriously wrong."
An example of when empty catch-clauses are appropriate:
Say that you are using someone elses code that opens a file for reading, given the absolute path of the file. Most such routines throw exceptions if the file does not exist - it is the job of the client code (i.e. the code that calls the "open file routine") to ensure that the file exists before trying to open it. Exceptions will also be thrown if, for example, the user running the program does not have permissions to read the file.
Now, you might not really care why the file couldn't be opened, but if it couldn't you just want to keep going - in that case, you swallow all exceptions related to reading the file (in Java, likely an IOException of some sort). Note that you do not swallow all exceptions - only the ones related to opening the file!
After a very bad attempt at doing my homework, I decided it would be faster to abandon everything and start from scratch. Well not everything ... I copied this part since it worked perfectly so I saw no need to modify it. While maybe not perfect, it worked.
However now, when I compile just to test it out, I get an unexpected error:
Input error: java.io.EOFException.
Notice that "Input error" is from my catch(IOException ioe).
The file (fileName) is completely empty. Nothing in it. What could cause this. Is there a way to tell the ObjectInputStream to do nothing if the file is empty ?
Also I tested this out with an empty file on my other "iteration", didn't have this problem. I even named my file the same.
public Repository (String fileName) throws FileNotFoundException,
IOException,
SecurityException,
ClassNotFoundException {
this.fileName = fileName;
this.clients = new ArrayList<Client> ();
FileInputStream fileIn = null;
ObjectInputStream in = null;
try {
fileIn = new FileInputStream(this.fileName);
in = new ObjectInputStream(fileIn);
this.clients = (ArrayList<Client>) in.readObject();
} catch (FileNotFoundException fnfe) {
System.out.println("File not found, error: " + fnfe);
} catch (IOException ioe) {
System.out.println("Input error: " + ioe);
} catch (ClassNotFoundException cnfe) {
System.out.println("Class not found, error: " + cnfe);
} catch (SecurityException se) {
System.out.println(
"You do not have permission to access this file, error: "
+ se);
} finally {
if (fileIn != null)
fileIn.close();
if (in != null)
in.close();
}
Surely before
in = new ObjectInputStream(fileIn);
this.clients = (ArrayList<Client>) in.readObject();
you want to check the file size via File.length().
I assume if it's empty then you'd want to return an empty array list. You can't do that via deserialising an empty file. After all, even an empty array list has a non-zero size (and would need to identify itself as an array list via serialised attributes)
The file (fileName) is completely empty. Nothing in it.
That's exactly the problem. You cannot read an object (or an array) from an empty file. It will not find any data and throw an End-of-file-Exception (EOFException).
Even an empty array - when serialized to a file - will produce some data because the object stream will write the type (ArrayList) and the size of the array (0) to the file. When you try to read it, it will expect to find this data.