Issue
public class CloseableResource implements AutoCloseable {
private static boolean _closed = false;
int _n;
public CloseableResource(int n){
}
public void use() throws Exception{
throw new Exception("Exception");
}
@Override
public void close() throws Exception{
_closed = true;
}
public static boolean isClosed() {
System.out.println(_closed);
return _closed;
}
@Test
public void testAutoClose() {
boolean failed = false;
try (CloseableResource res = new CloseableResource(2)) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
assertTrue(CloseableResource.isClosed());
failed = true;
}
assertTrue(failed == true);
failed = false;
try (CloseableResource res = new CloseableResource(3)) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
fail("this code should not be reached");
failed = true;
} finally {
assertTrue(CloseableResource.isClosed());
}
assertTrue(failed == false);
}
I am trying to make that test work, the close method seems to work but I can't figure out why the test doesn't, it always ends up with fail("this code should not be reached"). I need some guidance please.
Solution
private static boolean _closed = false;
why is this static? Making it static sets it to true or false on all instances instead of on a specific instance. I am not sure this is the desired behavior. When you create a new CloseableResource
new resources will remain closed. In the constructor, you MUST set the static _close
back to false
. This will make your test pass, but it will make for a lousy implementation.
This is what I did to make it "work" with Java 8. With Java 8, there is no way that I know of to really test the auto-closeable attribute of your resource.
public class CloseableResource implements AutoCloseable {
private boolean _closed = false;
int _n;
public CloseableResource() {
_n = 1;
}
// public CloseableResource(int n) {
// _n = n;
// }
public void use() throws Exception {
if (_closed) {
throw new Exception("Attempting to use a closed resource");
}
}
@Override
public void close() throws Exception {
if(_closed) {
throw new Exception ("Attempting to close a closed resource");
}
_closed = true;
}
public boolean isClosed() {
System.out.println(_closed);
return _closed;
}
@Test
public void testAutoClose() {
CloseableResource res = new CloseableResource();
try {
assertTrue(res != null);
res.use();
res.close();
} catch (Exception e) {
fail("This code should not be reached");
}
try {
assertTrue(res != null);
res.use();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to use a closed resource"));
}
try {
res.close();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to close a closed resource"));
}
}
}
However, if using Java 9 or greater, you can declare the resource outside the try (it will be effectively final); thus allowing you to test the auto-closeable attribute of your resource effectively.
@Test
public void testAutoClose() {
CloseableResource res = new CloseableResource();
try(res) {
assertTrue(res != null);
res.use();
} catch (Exception e) {
fail("This code should not be reached");
}
try {
res.use();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to use a closed resource"));
}
try {
res.close();
} catch (Exception e) {
assertTrue(e.getMessage().equals("Attempting to close a closed resource"));
}
}
This will allow you to use the same object to test all conditions in the same test.
Answered By - hfontanez
Answer Checked By - Marie Seifert (JavaFixing Admin)