10

I have something like

@Test(expected = IllegalArgumentException.class)
public void cdIntoNonExistantFolder() {
    cdTool.changeDirectory("nonexistant");
    assertThat(cdTool.getStatusCode(), not(equalTo(0)));
}

I believe the assertThat does not run as changeDirectory will throw the exception. Is it possible to make it still run?

Jiew Meng
  • 84,767
  • 185
  • 495
  • 805

4 Answers4

17

You could use a finally:

@Test(expected = IllegalArgumentException.class)
public void cdIntoNonExistantFolder() {
    try {
        cdTool.changeDirectory("nonexistant");
    }
    finally {
        assertThat(cdTool.getStatusCode(), not(equalTo(0)));
    }
}
MattR
  • 6,908
  • 2
  • 21
  • 30
6

I'd rather avoid any try/catch structures in unit-tests. Here's one possibility with Catch-Exception:

@Test
public void cdIntoNonExistantFolder() {
    catchException(cdTool).changeDirectory("nonexistant");

    assertThat(caughtException(), instanceOf(IllegalArgumentException.class));
    assertThat(cdTool.getStatusCode(), not(equalTo(0)));
}

or with JUnit 5:

@Test
public void cdIntoNonExistantFolder() {
    expectThrows(IllegalArgumentException.class, () -> {
        cdTool.changeDirectory("nonexistant");
    });

    assertThat(cdTool.getStatusCode(), not(equalTo(0)));
}
fgb
  • 18,439
  • 2
  • 38
  • 52
2

I prefer avoiding using the expected exception annotation. The reason is often there are "arrange" statements prior to the "act" portion of a test. These "arrange" sections could thrown the expected exception and the test would pass with a false positive.

Instead, I would use a try/catch structure around the method-under-test.

@Test
public void cdIntoNonExistantFolder() {
    try {
        cdTool.changeDirectory("nonexistant");
        Assert.fail("Should have thrown IllegalArgumentException");
    }
    catch (IllegalArgumentException e) {
        Assert.assertTrue(true);
        assertThat(cdTool.getStatusCode(), not(equalTo(0)));
    }
}

Two things to note:

  1. The try block NEEDS to have an Assert.fail() method
  2. I use the Assert.assertTrue(true); statement in the catch block to show that this is the path intended.
Robert Greathouse
  • 1,024
  • 1
  • 10
  • 18
  • 1
    You can avoid the false positive by using the ExpectedException rule and only set this after you have done all your "arrange" statements. – steinybot Jan 29 '15 at 01:52
-4

Create a new method, and put your assert in that method, annotate that method @After

@Test(expected = IllegalArgumentException.class)
public void cdIntoNonExistantFolder() {
    cdTool.changeDirectory("nonexistant");
}

@After
public void after() {
    assertThat(cdTool.getStatusCode(), not(equalTo(0)));
}
tanghao
  • 4,073
  • 2
  • 13
  • 17