Java Autocloseable Test

744 Views Asked by At
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.

1

There are 1 best solutions below

0
hfontanez On BEST ANSWER

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.