How can I unit test this inputStream has been closed? - java

I have a Runnable along the lines of:
public void run() {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
//more stuff here
}
catch (Exception e) {
//simplified for reading
}
finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}
}
How do I test inputStream.close() was invoked? I am currently using Mockito and JUnit. I know injecting the inputStream in is an idea, but I don't want the resources to be used until run?() is called, hence it being a local variable. So how can I redesign my code in a way that allows me to test whether close was called?

If I understood the task correctly it could be like this
static boolean isClosed;
public void run() {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file) {
#Override
public void close() throws IOException {
isClosed = true;
super.close();
}
};
// more stuff here

As there is no reason to expose the InputStream outside of the scope of this method you have a testing problem.
But I assume you don't directly care about the InputStream being closed. You want to test that because you've been told it's good practice (and it is). But I think what you actually care about is the negative impact of the stream being left open. What is the effect?
Try modifying this method so it does not close the stream, then execute it many times over. Do you get a memory leak, or run out of file handles or some other tomfoolery? If so, you have a reasonable test.
Alternatively, just go ahead and expose a decorated InputStream that can tell you if it has been closed or not. Make it package protected. That's the "impure", but pragmatic approach.

To check if the close() method is called, you can use Mockito.spy() to create a proxy object that can memorize calls. Spy delegates all the calls to the underlying InputStream, just memorizes what happened:
InputStream inputStreamSpy = Mockito.spy(inputStream);
// a code that is expected to close your stream goes here ...
Mockito.verify(inputStreamSpy).close();
This won't solve your problems with injecting instance of InputStream, actually. It seems like you need some kind of factory, that can open a stream for you, and you can mock that factory in unit tests. Let's call this factory a FileSystem:
public class FileSystem {
public FileInputStream newFileInputStream(File file) {
return new FileInputStream(file);
}
}
Now, you can inject an instance of the FileSystem, and it won't use resources before run method is executed:
public void run() {
InputStream inputStream = null;
try {
inputStream = fileSystem.newFileInputStream(file);
//more stuff here
}
catch (Exception e) {
//simplified for reading
}
finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}
}
#Test
public void runShouldCloseInputStream() {
InputStream inputStream = ...
InputStream inputStreamSpy = Mockito.spy(inputStream);
FileSystem fileSystemMock = Mockito.mock(FileSystem.class);
when(mockFileSystem.newFileInputStream(Mockito.any(File.class)))
.thenReturn(inputStreamSpy);
MyRunnable instance = new MyRunnable(mockFileSystem);
instance.run();
verify(inputStreamSpy).close();
}
Spy can do more then just listening, you can teach it to alter behavior using Mockito.when(), just as you would do with a regular mock.

Kotlin implementation for testing a URL stream is closed
//close the connection
streamURL.close()
//stream should not be available if it is closed
try { streamURL.available() }
//java.net.URL provides simple "closed" message on IO URL
catch (ex: IOException) { Assert.assertEquals("closed", ex.message) }

You can write in the test something like:
try {
run();
} catch (IOException e) {
Assert.fail();
}
When your method will close strem and exception will occur, then test will fail.

You can do like this...
try
{
inputStream.readLine();
}
catch (IOException e)
{
Assert.assertEquals(e.getLocalizedMessage(), "Stream closed");
}

Related

Java Serialization: close streams in try or in a finally block?

I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block. Can someone explain to me why is that?
Example:
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch(IOException i) {
i.printStackTrace();
return;
} catch(ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Source: http://www.tutorialspoint.com/java/java_serialization.htm
The try-with-resources Statement
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Source =>http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
From documentation:
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.
The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.
So it means if you have some connection, stream or some other resources opened you have to be sure that they will be closed after your code block will be executed.
To avoid such ugly blocks you can use utility methods:
public void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// handle block
}
}
}
Since Java 8 (but it is not required) you can provide your own Exception handler with closing resource:
public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
handler.accept(ex);
}
}
}
Also, just for knowledge, there are two cases when finally block is not called. It means that in most cases it will be called.
If you are Java 7 or aboveā€¦
Don't close in finally block
The close method can throw an IOException and FileInputStream/ObjectInputStream can be null. When you use .close in finally, you must check null and try/catch again.
Use "try-with-resources Statement" instead
Using try-with-resources your code looks like this:
try(
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)
) {
e = (Employee) in.readObject();
// in.close();
// fileIn.close();
}
The try-with-resources syntax guarantees the resources implementing AutoCloseable interface will be closed automatically. So you don't need to call a close method on your code.
You should close connection in finally. As finally always going to execute whether it goes in try or catch.
Also we need to close every connection once it created.
try{
// statements
}catch (){
// statements
}
finally {
in.close();
fileIn.close();
}
I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block.
Examples that do it that way are poor examples. While closing a stream within a try block will work for simple one-shot examples, doing this in a case where the code might be executed multiple times is liable to lead to resource leaks.
The other Answers to this Question do a good job of explaining the right way(s) to close streams.
Can someone explain to me why is that?
It comes down to poor quality control on the tutorial sites; i.e. inadequate code reviewing.
The accepted answer certainly has a bug.
The close method can throw an IOException too. If this happens when
in.close is called, the exception prevents fileIn.close from getting
called, and the fileIn stream remains open.
It can implemented as below when multiple streams are involved:
} finally {
if ( in != null) {
try { in .close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException ex) {
// Again, there is nothing we can do if close fails
}
}
}
Or, take advantage of Closeable Interface
} finally {
closeResource(in);
closeResource(fileIn);
}
Method:
private static void closeResource(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
}
You should close in finally block.
It's a bad habit to close in try block.
try {
e = (Employee) in.readObject(); //Possibility of exception
} catch(IOException i) {
} catch(ClassNotFoundException c) {
} finally {
in.close();
fileIn.close();
}
When someone is writing a code by knowing it will throw an exception,he/she has to close the opened resources
You should always close in a finally block.
However, you can use try with resources.
Here's the link: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}

Getting a NullPointerException when I try to write an object to a server in Java

I have a small problem. I have trying to use a method in another class to send an object to the server I have. I am using Java with Sockets.
Method:
public void sendMessageToServer(String message) {
if (message != null) {
try {
serverComManager.outputStream.writeObject(message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Class trying to use the method:
sendMessage.sendMessageToServer("Hello");
The error is thrown at the line:
serverComManager.outputStream.writeObject(message);
Thank you in advance!
~Rane
EDIT: As requested, I have added the 'serverComManager' declaration as well as the code for that class. I have also included the full error. I hope this helps you understand my problem.
Declaration:
ServerCommunicationManager serverComManager = new ServerCommunicationManager();
Code for ServerCommunicationManager:
boolean connected;
//Setup
Socket clientSocket;
ObjectOutputStream outputStream;
ObjectInputStream inputStream;
public boolean connectToHost() throws UnknownHostException, IOException{
clientSocket = new Socket("localhost", 2444);
setupStreams(clientSocket);
if(clientSocket.isConnected()){
connected = true;
}else{
connected = false;
}
return connected;
}
private void setupStreams(Socket s) throws IOException{
outputStream = new ObjectOutputStream(s.getOutputStream());
inputStream = new ObjectInputStream(s.getInputStream());
}
Error:
Exception java.lang.NullPointerException
at SendToServer.sendMessageToServer(SendToServer.java:16)
at DissconnectClient.dissconnectFromServer(DissconnectClient.java:15)
Error Lines:
DissconnectClient 15: sendMessage.sendMessageToServer(abortConnectionKeyword);
SendToServer 16: serverComManager.outputStream.writeObject(message);
NOTE: DisconnectClient is one of the classes I am writing with. Here is the class code:
public class DissconnectClient {
//Variables
private final String keyword = "DISSCONNECT";
//Setup
SendToServer sendMessage = new SendToServer();
public void dissconnectFromServer(){
sendMessage.sendMessageToServer(keyword);
}
}
I cannot see where do you assign a value of "serverComManager" or where do you create an isntance of this. Maybe in a constructor method ot the class which has the method "sendMessageToServer" you're doing something like this.serverComManager = (...). I'm not sure how you are handle the logic of "serverComManager" but so far, my approach to solve the issue would be the following (if I'm writing a client that sends a message to the server). And considering there's no code provided for your "serverConnManager", maybe you could identify something missing in your current implementation.
public void sendMessageToServer(String message) {
if (message != null) {
try {
//Assume I already have an instance of client Socket:
//Socket outgoingConn = new Socket(host, port)
//1. I get the OutputStream of my outgoing connection
OutputStream outStream = outgoingConn.getOutputStream();
//2. Create an object output stream
ObjectOutputStream objectWriter = new ObjectOutputStream(outStream);
//3. Write the object
objectWriter.writeObject(message);
//Close the io if required (would recommend try-with-resources if using jdk7)
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
If you are working just with String messages, BufferedWriter orBufferedReadr would be enough, if you try to handle complex objects that can be both "beans" or Strings, better if you create something like:
public class MessageBean implements Serializable {
private MessageType type;
private Object param;
//Getters/Setters
}
MessageType could be an enum specifying the type of objects supported, since param field is an object you can handle as an String or as a bean. Then work based on the MessageType or using the "instanceof". But Well, this is just a suggestion if you want to try something further.
Hope it helps. Happy coding!
Regards.

Is attached code safe from open file leak

Assuming Java6, is this code safe from file descriptor leak:
{
InputStream in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
try {
// do whatever, possibly throwing exception
} finally {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
Edit: To make question seem less obvious, to state it other way, is above code equal to this longer code:
{
InputStream in = null;
try {
in = fileObject.getReadStream();
// fileObject cleans it's internal state in case it throws exception
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem
}
}
}
}
That is, does it matter whether a call to a method which returns opened stream or throws exception is immediately before try, or inside the try block?
Yes, fine. Does not even merit an answer. A variant (I less use) is:
InputStream in = null;
try {
in = fileObject.getReadStream();
// do whatever, possibly throwing exception
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ex) {
// failure to close input stream is no problem if everything else was ok
}
}
}
I'm a student not very familiar with Java, but I wish I can help you a litltle.
I think that the piece of code can't keep you from the problem of file descriptor leak. Though you have let a try clouse wurround the in.close methord, but that won't help if
the in.close method throws some exceptions.

File I/O without clutering of exceptions

What is the best way to use e.g. FileOutputStream without cluttering my code.
Example the following code:
What I need to do is:
FileOutputStream fOut = new FileOutputStream(file);
while(!Thread.currentThread().isInterrupted()){
fOut.write(data);
//other code
}
But if I add the exception handling is all messy. I thought for example something like the following:
private FileOutputStream openStream(String file){
try{
return new FileOutputStream(file);
}
catch(FileNotFoundException e){
return null;
}
}
But then it makes the logic weird. I mean when I close the stream, e.g. in another method etc.
What is the way to get clearer code
What about a wrapper like this:
public class StreamWrapper {
private FileOutputStream fileOutputStream;
public FileOutputStream open(String file) {
try {
fileOutputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
// Define action
}
return fileOutputStream;
}
public void close() {
try {
fileOutputStream.close();
} catch (IOException e) {
// Define action
}
}
}
And use it like:
StreamWrapper wrapper = new StreamWrapper();
FileOutputStream fOut = wrapper.open("file");
// something
wrapper.close();
There is no direct way of avoiding checked exceptions in Java, unfortunately. Few work-arounds:
Use different language
Both groovy and scala treat checked exceptions as unchecked.
try-with-resources idiom in Java 7
It doesn't really help with catch, but substantially reduces the amount of finally blocks surrounding close().
Throwables.propagate(Throwable) in Guava
Avoid returning null and swallowing exceptions:
private FileOutputStream openStream(String file){
try{
return new FileOutputStream(file);
}
catch(FileNotFoundException e){
return Throwables.propagate(e);
}
}
See also: Long try statements.
Applicative exceptions are there for a reason (and nobody likes RT exceptions...)
You could use a factory to hide the exception handling, but the "catch" clause would have to be in your code somewhere.
One idea is to implement your own wrapper to FileOutputStream that will swallow the exception during instantiation, but since the exception is thrown at the constructor you'll end up in an unstable state if the file indeed doesn't exists.
public class MyFileOutputStream {
private FileOutputStream fis;
public MyFileOutputStream(File file){
try{
fis = new FileOutputStream(file);
} catch (FileNotFoundException e){
fis = null;
}
}
public boolean isOpened(){
return fis!=null;
}
public void write(Byte b) throws IOException {
fis.write(b);
}
}
There are couple options that you can do:
First of all you sample code is good only thing is "in case of a exception you are returning a null object". So rather than returning a FileOutputStream object you can actually send a boolean and store the FileOutputStream object as a class variable.
So if other program want to access that can make this call and the caller will get True/False depending on whether it could create a object successfully or not, and if that is True then can use the class variable for the FileOutputStream object. I am attaching some sample code with that:
FileOutputStream fOutSt;
private boolean isOpenStream(String file){
try{
fOutSt = new FileOutputStream(file);
return true;
}
catch(FileNotFoundException e){
return false;
}
}
Then the caller can make call like:
if(isOpenStream) {
obj.GetfOutSt;
}

Can I avoid such cumbersome try...catch block

Usually, when dealing with Java IO code, here is what I wrote
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
// I put the close code in finally block, to enture the opened
// file stream is always closed even there is exception happened.
if (out != null) {
// Another try catch block, troublesome.
try {
out.close();
} catch (IOException ex) {
}
}
}
As you can see, while I try to close the file stream, I need to deal with another try...catch block.
Look troublesome :(
Is there any way I can avoid? I don't feel comfortable in putting the close code in non-finally block, as exception caused by other codes will make no chance for "close" being called.
It is very important that you close streams in a finally. You can simplify this process with a utility method such as:
public static void closeStream(Closeable closeable) {
if(null != closeable) {
try {
closeable.close();
} catch(IOException ex) {
LOG.warning("Failed to properly close closeable.", ex);
}
}
}
I make it a point of at least logging a stream close failure. The usage then becomes:
FileOutputStream out = null;
try
{
out = new FileOutputStream("myfile.txt");
// More and more code goes here...
}
catch (Exception e)
{
}
finally
{
closeStream(out);
}
In Java 7 I believe that streams will be closed automatically and the need for such blocks should be mostly redundant.
Automatic Resource Management is coming in Java 7 which will automatically provide handling of this. Until then, objects such as OutputStream, InputStream and others implement the Closeable interface since Java 5. I suggest you provide a utility method to safe close these. These methods generally eat exceptions so make sure that you only use them when you want to ignore exceptions (e.g. in finally method). For example:
public class IOUtils {
public static void safeClose(Closeable c) {
try {
if (c != null)
c.close();
} catch (IOException e) {
}
}
}
Note that the close() method can be called multiple times, if it is already closed subsequent calls will have no effect, so also provide a call to close during the normal operation of the try block where an exception will not be ignored. From the Closeable.close documentation:
If the stream is already closed then invoking this method has no effect
So close the output stream in the regular flow of the code and the safeClose method will only perform close if something failed in the try block:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
//...
out.close();
out = null;
} finally {
IOUtils.safeClose(out);
}
Discussion at
Try-catch-finally and then again a try catch
and
Is there a preference for nested try/catch blocks?
basically, the question is whether a close() exception is worth catching.
Project Lombok provides a #Cleanup annotation that removes the need for try catch blocks all together. Here's an example.
I tend to use utility functions for this:
public static void safeClose(OutputStream out) {
try {
out.close();
} catch (Exception e) {
// do nothing
}
}
which changes the code to the slightly more palatable:
FileOutputStream out = null;
try {
out = new FileOutputStream("myfile.txt");
// do stuff
} catch (Exception e) {
// do something
} finally {
safeClose(out);
}
You can't really do much better in Java at least until Java 7 when (hopefully) ARM ("Automatic Resource Management") blocks will help somewhat.
Write a method that looks something like below; call from your finally block...
static void wrappedClose(OutputStream os) {
if (os != null) {
try {
os.close();
}
catch (IOException ex) {
// perhaps log something here?
}
}
Separate your try/catch and try/finally blocks.
try
{
FileOutputStream out = new FileOutputStream("myfile.txt");
try
{
// More and more code goes here...
}
finally
{
out.close();
}
}
catch (Exception e)
{
//handle all exceptions
}
The outer catch will also catch anything thrown by the close.

Categories

Resources