-2
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.

Gabriel N
  • 13
  • 2
  • 1
    You need to explain what the code is *intended* to do. – Stephen C Oct 29 '22 at 13:51
  • Or to put it another way, why do you >think< that that statement shouldn't be reached? – Stephen C Oct 29 '22 at 13:54
  • The test checks if the Autocloseable method is working. The first test goes ok, the second test has a fail asset which makes the second test not pass. I don't undestand why or how to make it work. edit. If it reaches that fail statement the test fails. – Gabriel N Oct 29 '22 at 13:56
  • Well, to my mind the only problem is that `fail("this code should not be reached");` is incorrect. If `use()` throws an `Exception`, then you should be able to catch it there. That's just how *try with resources* works. – Stephen C Oct 29 '22 at 13:59
  • Hint: read about suppressed exceptions; https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html#suppressed-exceptions – Stephen C Oct 29 '22 at 14:03
  • Gabriel, I know the question is already closed, but I posted an answer for you before this. Please check it out and mark it as the selected answer if it works for you. If not, post a comment under my answer so I could refine it for you. – hfontanez Oct 29 '22 at 15:11
  • @hfontanez I can't modify the test so I have to make due with what I have. Thank you for helping me. – Gabriel N Oct 29 '22 at 16:08
  • 1
    I've used the if(_closed) in the use method and it worked. I've been struggling for quite a while with this. I am learning. Thank you. – Gabriel N Oct 29 '22 at 16:23

1 Answers1

0

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.

hfontanez
  • 5,774
  • 2
  • 25
  • 37